high-level programming languages high-level features relative to assembly language high-level...
TRANSCRIPT
High-level programming High-level programming languageslanguages
High-level features relative to assembly languageHigh-level features relative to assembly language ‘‘Highness’ = degree of abstractionHighness’ = degree of abstraction
machine independencemachine independence efficient implementation does not depend on a specific efficient implementation does not depend on a specific
machine instruction setmachine instruction set relatively easy goalrelatively easy goal
ease of programmingease of programming hard goalhard goal more aesthetics, trial and error than science ?more aesthetics, trial and error than science ?
Programming language designProgramming language design find the right abstractionsfind the right abstractions
NameName
Mnemonic character string to represent something Mnemonic character string to represent something elseelse usually identifiersusually identifiers some languages allow names like ‘+’ & ‘:=‘some languages allow names like ‘+’ & ‘:=‘
Enables programmers to refer to variables etc. using
symbolic names rather than low-level hardware addresses
abstract their control and data structures express the purpose or function instead of implementationexpress the purpose or function instead of implementation make programs manageablemake programs manageable control abstraction: subroutinescontrol abstraction: subroutines data abstraction: classes (for example)data abstraction: classes (for example)
Binding & Binding Time...
Binding an association between a name and the thing that is named has usually some scope (part of the program where active)
Binding time the time at which any implementation decision is made to
create a binding Language design time
the design of specific program constructs (syntax) primitive types meaning (semantics)
Language implementation time fixation of implementation constants such as I/O, run-time memory sizes, how to handle arithmetic overflow,
…
...Binding times...Binding times
Program writing time programmer’s choice of algorithms and data structures
Compile time translation of high-level constructs to machine code choice of memory layout for objects
Link time multiple object codes (machine code files) and libraries
are combined into one executable Load time
operating system loads the executable in memory Run time
program executes
Run time in detailRun time in detail
program start-upprogram start-up module entrymodule entry elaboration (declaration is ’seen’)elaboration (declaration is ’seen’) subroutine entrysubroutine entry block entryblock entry statement executionstatement execution
Nature of bindingsNature of bindings
Static: things bound before executionStatic: things bound before execution Dynamic: execution-time bindingsDynamic: execution-time bindings Early bindingEarly binding
efficiency (efficiency (e.g.e.g. addressing a global variable in C) addressing a global variable in C) languages tend to be compiledlanguages tend to be compiled
Late bindingLate binding flexibility (flexibility (e.g.e.g. polymorphism in Smalltalk) polymorphism in Smalltalk) languages tend to be interpretedlanguages tend to be interpreted
Our current interestOur current interest binding of binding of identifiersidentifiers to to variablesvariables they name they name note: all data has not to be named (note: all data has not to be named (e.g.e.g. dynamic storage) dynamic storage)
Things we have to keep Things we have to keep track oftrack of
creation ofcreation of objectsobjects bindingsbindings
references to variables (which use bindings)references to variables (which use bindings) deactivation and reactivation of bindingsdeactivation and reactivation of bindings destruction ofdestruction of
bindingsbindings objectsobjects
if we don’t keep good track of them we may getif we don’t keep good track of them we may get garbage: object that outlives it's binding andgarbage: object that outlives it's binding and dangling references: bindings that outlive their objectsdangling references: bindings that outlive their objects
LifetimeLifetime
Binding lifetimeBinding lifetime time between the creation and destructiontime between the creation and destruction typically determined by the typically determined by the scopescope of the of the
bindingbinding region where binding is region where binding is activeactive
Object lifetimeObject lifetime time between the creation and destructiontime between the creation and destruction not necessarily the same as binding lifetime !not necessarily the same as binding lifetime !
e.g.e.g. objects passed as reference parameters objects passed as reference parameters generally corresponds to the generally corresponds to the storage allocation storage allocation
mechanism that is used to allocate/deallocate mechanism that is used to allocate/deallocate object’s spaceobject’s space
Storage allocationStorage allocation
StaticStatic objects objects have absolute (and same) address through the have absolute (and same) address through the
program executionprogram execution space is ‘part of the program’space is ‘part of the program’
StackStack objects objects allocated/deallocated in LIFO orderallocated/deallocated in LIFO order (usually) in conjunction of subroutine calls/exits(usually) in conjunction of subroutine calls/exits
HeapHeap objects objects can be allocated/deallocated at arbitrary timescan be allocated/deallocated at arbitrary times management is more complex than with a management is more complex than with a
stackstack
Static objectsStatic objects
Global variablesGlobal variables Translated machine codeTranslated machine code
subroutine locations in particularsubroutine locations in particular ConstantsConstants
large ones in ‘constant pool’large ones in ‘constant pool’ small ones (small ones (e.g.e.g. integers) stored as part of instructions integers) stored as part of instructions
Subroutine variables that are declared Subroutine variables that are declared staticstatic Run-time support tables (produced by the Run-time support tables (produced by the
compiler)compiler) symbol table, dynamic type checking, exception symbol table, dynamic type checking, exception
handling, garbage collection, ... handling, garbage collection, ... Note: processor-supported memory protection is Note: processor-supported memory protection is
possible for constant datapossible for constant data
Static or non?Static or non?
Local variables in non-recursive languagesLocal variables in non-recursive languages e.g. early Fortranse.g. early Fortrans all data (subroutines included) can be allocated all data (subroutines included) can be allocated
staticallystatically pros: faster executionpros: faster execution cons: wastes space, bad programming practicescons: wastes space, bad programming practices
Local constantsLocal constants compile-time constantscompile-time constants can be allocated can be allocated
staticallystatically elaboration-time constants elaboration-time constants must be allocated must be allocated
from stack from stack each invocation may have a different valueeach invocation may have a different value
Other information associated Other information associated with subroutineswith subroutines
Arguments and return valuesArguments and return values compilers try to place these in registers if compilers try to place these in registers if
possiblepossible if not, then the stack is usedif not, then the stack is used
Temporary variablesTemporary variables hold intermediate values of complex calculationshold intermediate values of complex calculations registers / stackregisters / stack
Bookkeeping informationBookkeeping information return address (dynamic link)return address (dynamic link) saved registers (of the caller)saved registers (of the caller) ......
Why a stack?Why a stack?
Subroutine call / return is ‘stack-like’Subroutine call / return is ‘stack-like’ stack is the natural data structure to stack is the natural data structure to
support data allocation & deallocationsupport data allocation & deallocation Allows recursionAllows recursion
several several instancesinstances of same subroutine of same subroutine can be activecan be active
Allows re-using spaceAllows re-using space even when no recursion is usedeven when no recursion is used
Maintaining the stackMaintaining the stack
Each subroutine call creates a Each subroutine call creates a stack framestack frame a.k.a a.k.a activation recordactivation record bottom of the frame: arguments and returnsbottom of the frame: arguments and returns
easy access for the callereasy access for the caller always at same offsetalways at same offset
top of the frame: local variables & tempstop of the frame: local variables & temps compiler decides relative orderingcompiler decides relative ordering
Maintenance of stack is done by (see Section 8.2)Maintenance of stack is done by (see Section 8.2) prologue & epilogueprologue & epilogue in the subroutine in the subroutine
saves space to do much heresaves space to do much here calling sequencecalling sequence in the caller in the caller
instructions immediately before/after call/returninstructions immediately before/after call/return may may save time to do much heresave time to do much here interprocedural optimizations possibleinterprocedural optimizations possible
Addressing stack objectsAddressing stack objects
Offsets of variables Offsets of variables withinwithin a frame can be decided a frame can be decided at compile-timeat compile-time
Locations of frames themselves may vary during Locations of frames themselves may vary during executionexecution
Many machines have Many machines have a special a special frame pointer frame pointer register (fp)register (fp) load/store instructions supporting indirect addressing via load/store instructions supporting indirect addressing via
fpfp Address = fp + offset (Fig. 3.2)Address = fp + offset (Fig. 3.2)
locals, temps: negative offsetlocals, temps: negative offset arguments, returns: positive offsetarguments, returns: positive offset stack grows ‘downward’ from high addresses to low onesstack grows ‘downward’ from high addresses to low ones push/pop instructions to manipulate both fp and datapush/pop instructions to manipulate both fp and data
Heap-Based allocationHeap-Based allocation
Heap is here not a priority queueHeap is here not a priority queue region of storage to support allocation/deallocation at arbitrary region of storage to support allocation/deallocation at arbitrary
timestimes necessity for dynamic data structuresnecessity for dynamic data structures
Many space-management strategiesMany space-management strategies should be part of your data structures course?should be part of your data structures course? space & speed concernsspace & speed concerns space: internal & external space: internal & external fragmentationfragmentation
InternalInternal allocation of a block larger than requiredallocation of a block larger than required happens because of standard-sized blockshappens because of standard-sized blocks
ExternalExternal blocks are scattered around the heapblocks are scattered around the heap lot of free space but in small pieceslot of free space but in small pieces
Block allocationBlock allocation
Maintain all unallocated blocks in one listMaintain all unallocated blocks in one list a.k.a a.k.a free listfree list at each allocation request, look for a block of appropriate at each allocation request, look for a block of appropriate
sizesize StrategiesStrategies
First-fit: return first large enoughFirst-fit: return first large enough Best-fit: return smallest block large enoughBest-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 if the block found is much larger than the request, split it
in 2 and return the other half to free listin 2 and return the other half to free list DeallocationDeallocation
add to free list and merge with adjacent regions if add to free list and merge with adjacent regions if possiblepossible
Reducing allocation timeReducing allocation time
Scanning the free list Scanning the free list takes linear time in the # of free blockstakes linear time in the # of free blocks maintain separate lists for different maintain separate lists for different
(standard) sizes(standard) sizes Fast allocationFast 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 heapsBuddy systems & Fibonacci heaps block sizes powers of 2 or Fibo numbersblock sizes powers of 2 or Fibo numbers
Garbage collectionGarbage collection
External fragmentation can not be External fragmentation can not be avoidedavoided ‘‘checkerboard’ the heapcheckerboard’ the heap we end up with a situation wherewe end up with a situation where
we have a lot of free spacewe have a lot of free space but no blocks large enoughbut no blocks large enough heap must be compacted by moving the heap must be compacted by moving the
allocated blocksallocated blocks complicated because all the references to these complicated because all the references to these
blocks must be updated, too!blocks must be updated, too!
Explicit and implicit Explicit and implicit deallocationdeallocation
Allocation is always triggered by some Allocation is always triggered by some program actionprogram action
Deallocation can be eitherDeallocation can be either explicitexplicit
Pascal, CPascal, C simple, efficient, immediatesimple, efficient, immediate allows ‘hand-tailored’ storage managementallows ‘hand-tailored’ storage management
or implicit or implicit Java, C++, functional languagesJava, C++, functional languages garbage collector starts whenever space gets lowgarbage collector starts whenever space gets low complex, time-consumingcomplex, time-consuming
GC or not to GC?GC or not to GC?
Explicit memory management is more efficientExplicit memory management is more efficient ButBut
manual deallocation errors are among the most common manual deallocation errors are among the most common and costly bugsand costly bugs
too fast deallocation too fast deallocation dangling references dangling references forgotten deallocation forgotten deallocation memory leaks memory leaks
Automatic GC is considered an essential feature Automatic GC is considered an essential feature of modern languagesof modern languages GC algorithms have improvedGC algorithms have improved implementations are more complex in general (so implementations are more complex in general (so
adding GC plays not a big role)adding GC plays not a big role) large applications make benefits of GC greaterlarge applications make benefits of GC greater
ScopeScope
Scope (of a binding)Scope (of a binding) the (textual) part of the program where the the (textual) part of the program where the
binding is activebinding is active Scope (in general) is aScope (in general) is a
program section of maximal size in which program section of maximal size in which no bindings change or at leastno bindings change or at least no re-declarations are permittedno re-declarations are permitted
Lifetime and scope are not necessarily the Lifetime and scope are not necessarily the samesame
ElaborationElaboration
Subroutine entrance Subroutine entrance new scope new scope opensopens create bindings for new local variablescreate bindings for new local variables deactivate bindings for global variables that are deactivate bindings for global variables that are
redeclaredredeclared Subroutine exit Subroutine exit scope closes scope closes
destroy bindings for local variablesdestroy bindings for local variables reactivate bindings for global variables that were reactivate bindings for global variables that were
deactivateddeactivated ElaborationElaboration
process of creating bindings when entering a new scopeprocess of creating bindings when entering a new scope also other tasks, for example in Ada:also other tasks, for example in Ada:
storage allocationstorage allocation starting tasks (processes)starting tasks (processes) propagating exceptionspropagating exceptions
Scope rulesScope rules
Referencing environmentReferencing environment of a statement of a statement the set of active bindingsthe set of active bindings corresponds to a collection of scopes that are examined corresponds to a collection of scopes that are examined
(in order) to find a binding(in order) to find a binding Scope rulesScope rules
determine that collection and its orderdetermine that collection and its order Static (lexical) scope rulesStatic (lexical) scope rules
scope is defined in terms of the physical (lexical) structure scope is defined in terms of the physical (lexical) structure of the programof the program
typically the most recent (active) binding is chosentypically the most recent (active) binding is chosen we study mostly (and first) these herewe study mostly (and first) these here
Dynamic scope rulesDynamic scope rules bindings depend on the current state of program bindings depend on the current state of program
executionexecution
Static scopeStatic scope
Related to program structureRelated to program structure Basic: one scope (static & global)Basic: one scope (static & global) Fortran: global & local scopesFortran: global & local scopes
COMMONCOMMON blocks blocks aim: share global data in separately compiled subroutinesaim: share global data in separately compiled subroutines typing errors possibletyping errors possible
EQUIVALENCE EQUIVALENCE of variablesof variables aim: share (and save) spaceaim: share (and save) space predecessor of variant/union typespredecessor of variant/union types
lifetime of a local variable?lifetime of a local variable? semantically: execution of the subroutinesemantically: execution of the subroutine possible to possible to SAVE SAVE variables (static allocation)variables (static allocation) in practice in practice all all variables variables maymay behave as if behave as if SAVESAVEd d bad bad
programmingprogramming
Nested program structureNested 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 declared inside a subroutine thing X is thing X is
notnot visible outside that subroutine visible outside that subroutine Algol 60, Pascal, Ada, ...Algol 60, Pascal, Ada, ...
Resolving bindingsResolving bindings closest nested scope ruleclosest nested scope rule subsequent declarations may subsequent declarations may hidehide surrounding surrounding
ones (temporarily)ones (temporarily) built-in/predefined bindings: special outmost built-in/predefined bindings: special outmost
scopescope Example in Figure 3.4Example in Figure 3.4
Non-local referencesNon-local references
Nested subroutine may refer to objects declared in Nested subroutine may refer to objects declared in other subroutines (surrounding it)other subroutines (surrounding it) example 3.4: P3 can access A1, X and A2example 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-timeneed to find the corresponding frame at run-time
DifficultyDifficulty 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 caller’s scope is notnot (always) the lexically surrounding (always) the lexically surrounding
scopescope however, that surrounding scope however, that surrounding scope mustmust have a stack frame have a stack frame
somewhere below in the stacksomewhere below in the stack we can get to P3 only by making it visible firstwe can get to P3 only by making it visible first P3 gets visible after P1 & P2 have been calledP3 gets visible after P1 & P2 have been called
Accessing non-local stack Accessing non-local stack objectsobjects
Parent frameParent frame most recent invocation of the lexically surrounding most recent invocation of the lexically surrounding
subroutinesubroutine Augment stack frame with Augment stack frame with static linkstatic link
pointer to parent framepointer to parent frame outermost frame: parent = niloutermost frame: parent = nil links form a links form a static chain static chain through all scopesthrough all scopes
AccessingAccessing routine at nesting depth k refers to an object at depth jroutine 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 usualuse offset in that ancestor frame as usual
Figure 3.5Figure 3.5
Declaration orderDeclaration order
Can an identifier be used before it’s declared?Can an identifier be used before it’s declared? x declared somewhere in block Bx declared somewhere in block B does the scope of x include all of B or only the portion does the scope of x include all of B or only the portion
following the declaration?following the declaration? A lot of variation between languagesA lot of variation between languages
see book examples on pages 121-123see book examples on pages 121-123 complicating factorscomplicating factors
mutual recursion (e.g. in type definitions)mutual recursion (e.g. in type definitions) redefinitionsredefinitions
one workaround: separate ’declaration’ from ’definition’one workaround: separate ’declaration’ from ’definition’ declaration introduces the name (and defines it’s scope)declaration introduces the name (and defines it’s scope) definition does the bindingdefinition does the binding require ’declare’ before userequire ’declare’ before use C, C++C, C++
Nested blocks & scopeNested blocks & scope
Variable definitions in block statementsVariable definitions in block statements either at the beginning of the block oreither at the beginning of the block or
C, AdaC, Ada anywhere where a statement may appearanywhere where a statement may appear
C++, JavaC++, Java scope extends to the end of the current blockscope extends to the end of the current block
space allocated from the stack framespace allocated from the stack frame no extra runtime operations neededno extra runtime operations needed space saved by letting allocations overlap each otherspace saved by letting allocations overlap each other
Holes in scopesHoles in scopes
Name-object binding N-O1Name-object binding N-O1 hidden by a nested declaration N-O2hidden by a nested declaration N-O2 has a has a hole hole in it’s scope (for the lifetime of that in it’s scope (for the lifetime of that
nested declaration)nested declaration) object O1 is inaccessible via Nobject O1 is inaccessible via N
Scope resolution operatorsScope resolution operators allow programmer to explicitly use ‘hidden’ allow programmer to explicitly use ‘hidden’
bindingsbindings a.k.a a.k.a qualifiersqualifiers Ada: Ada: My_Proc.X My_Proc.X ((X X declared in declared in My_ProcMy_Proc)) C++: C++: ::X::X (global X) (global X)
ModulesModules
Great tool to divide programming effortGreat tool to divide programming effort information hidinginformation hiding
details are visible only to parts that really need themdetails are visible only to parts that really need them reduces the ‘cognitive load’ of programmersreduces the ‘cognitive load’ of programmers
minimize the amount of information required to understand minimize the amount of information required to understand any part of the systemany part of the system
changes & updates localized within single moduleschanges & updates localized within single modules Other benefitsOther benefits
reduces name clashesreduces name clashes data integrity: only routines inside a module update data integrity: only routines inside a module update
certain objectcertain object errors are localizederrors are localized
Information hiding using Information hiding using subroutines?subroutines?
Hiding is limited to objects defined inside a Hiding is limited to objects defined inside a routineroutine lifetime = execution of the routinelifetime = execution of the routine
Partial solution: use static local objectsPartial solution: use static local objects C: C: staticstatic, Algol: , Algol: ownown, ..., ... Example: Figure 3.6Example: Figure 3.6 ‘‘subroutines with memory’subroutines with memory’ ‘‘single-routine data abstractions’single-routine data abstractions’ what if the abstraction requires many routines?what if the abstraction requires many routines?
Module: multiple-routine Module: multiple-routine abstractionabstraction
Combine and hide several routines & data Combine and hide several routines & data structuresstructures e.g. stack type, push and pop operationse.g. stack type, push and pop operations Ada: package, Clu: cluster, Modula-2: moduleAda: package, Clu: cluster, Modula-2: module objects inside a module areobjects inside a module are
visible to each othervisible to each other not not visible to the outside visible to the outside unlessunless explicitly explicitly exportedexported
objects outside a module areobjects outside a module are not not visible to the inside visible to the inside unlessunless explicitly explicitly importedimported
Example: Figure 3.7Example: Figure 3.7
Modules and bindingsModules and bindings
Bindings made inside a moduleBindings made inside a module are inactive outside of itare inactive outside of it but but not not destroyeddestroyed module-level objects have ‘same lifetime they module-level objects have ‘same lifetime they
would have without the enclosing module’would have without the enclosing module’ same as the scope they appear insame as the scope they appear in
Restrictions on export declarationsRestrictions on export declarations possible in many module-based languagespossible in many module-based languages variables exported read-onlyvariables exported read-only Modula-2: types exported as Modula-2: types exported as opaqueopaque
only certain primitive operations allowedonly certain primitive operations allowed
Headers and bodiesHeaders and bodies
Modules are often divided intoModules are often divided into header/declaration partheader/declaration part
definitions for users of the moduledefinitions for users of the module the the public public interface of the moduleinterface of the module may also contain private information (for compilation)may also contain private information (for compilation)
body/implementation partbody/implementation part definitions for the implementation of the moduledefinitions for the implementation of the module
Header and body parts can be compiled Header and body parts can be compiled separatelyseparately especially header can be compiled even if body does not especially header can be compiled even if body does not
exist (yet)exist (yet) and so can the users of the headerand so can the users of the header total recompilation unnecessary if only some modules total recompilation unnecessary if only some modules
are updatedare updated
Open and closed scopesOpen and closed scopes
Open scopeOpen scope no imports required (importing according to the no imports required (importing according to the
scope rules)scope rules) Ada packages, nested subroutines in most Algol Ada packages, nested subroutines in most Algol
family languagesfamily languages Selective scoping (Java)Selective scoping (Java)
A exports foo, B can use A.foo (without explicit A exports foo, B can use A.foo (without explicit importing)importing)
Closed scopeClosed scope all names must be explicitly importedall names must be explicitly imported import lists document the programimport lists document the program
nonlocal references are part of the interfacenonlocal references are part of the interface
Type manager modulesType manager modules
Modules support ‘naturally’ only the Modules support ‘naturally’ only the creation of one single instance of a given creation of one single instance of a given abstractionabstraction Figure 3.7 creates only one stackFigure 3.7 creates only one stack another stack needed another stack needed replicate code? replicate code?
Alternative organizationAlternative organization module is a module is a manager manager for the instances of the for the instances of the
type it implements (Fig. 3.8)type it implements (Fig. 3.8) additional routines to create/destroy instancesadditional routines to create/destroy instances additional parameter to each operation (the additional parameter to each operation (the
object in question)object in question) Clu: every module is a manager of some typeClu: every module is a manager of some type
Module typesModule types
Each module defines a typeEach module defines a type possible to declare (any number of) variables of that typepossible to declare (any number of) variables of that type Euclid, Simula, Clu (example in Fig. 3.9)Euclid, Simula, Clu (example in Fig. 3.9) automatic actionsautomatic actions
initialization (allocation, initial values) initialization (allocation, initial values) finalization (e.g. to return objects to heap)finalization (e.g. to return objects to heap)
Types and their operations are tightly bound to each Types and their operations are tightly bound to each otherother operations ‘belong’ to objects of the module typeoperations ‘belong’ to objects of the module type conceptuallyconceptually
type approach has a separate push for every stack (A.push(x))type approach has a separate push for every stack (A.push(x)) manager approach has one parameterized push for all stacksmanager approach has one parameterized push for all stacks
same implementation in practicesame implementation in practice
ClassesClasses
Concept that facilitates object-oriented Concept that facilitates object-oriented programmingprogramming
Module types augmented with Module types augmented with inheritance mechanisminheritance mechanism possible to define new modules ‘on top’ of possible to define new modules ‘on top’ of
existing ones (refinements, extensions)existing ones (refinements, extensions) objects inherit operations of other objects objects inherit operations of other objects
(no need to rewrite the code)(no need to rewrite the code)
Module types and scopesModule types and scopes
Note: applies also to classes if we forget Note: applies also to classes if we forget inheritanceinheritance
Every instance A of a module type hasEvery instance A of a module type has a separate copy of the module variablesa separate copy of the module variables which are visible when executing one of A’s operationswhich are visible when executing one of A’s operations
Indirect visibility (within same type)Indirect visibility (within same type) the the instance variablesinstance variables of B may be visible of B may be visible to another instance A of the same typeto another instance A of the same type if B is passed as a parameter of A’s operationif B is passed as a parameter of A’s operation
typical example: binary operations of C++typical example: binary operations of C++ opinions vary whether this is a good idea or notopinions vary whether this is a good idea or not
Dynamic scope...Dynamic scope...
Name-object binding decided at run-timeName-object binding decided at run-time usually the last active declarationusually the last active declaration thus, derived from the order in which thus, derived from the order in which
subroutines are called (Fig. 3.10)subroutines are called (Fig. 3.10) flow of control is unpredictable flow of control is unpredictable compilation compilation
impossibleimpossible Example languagesExample 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 shellsenvironment variables in command shells
...Dynamic scope...Dynamic scope
Dynamic scope Dynamic scope dynamic semantics dynamic semantics type checking in expressions and parameter type checking in expressions and parameter
passing must be deferred to run-timepassing must be deferred to run-time Simple implementationSimple implementation
maintain declarations in a stackmaintain declarations in a stack search stack top search stack top bottom to find bindings bottom to find bindings push/pop bindings when entering/leaving push/pop bindings when entering/leaving
subroutinessubroutines quite slowquite slow
lookup tables instead (provided names are known)lookup tables instead (provided names are known)
Dynamic scope is a bad Dynamic scope is a bad idea?idea?
ConsCons High run-time costsHigh run-time costs Non-local references are ‘unpredictable’Non-local references are ‘unpredictable’ Dynamic programs are hard to understandDynamic programs are hard to understand
see program in Fig. 3.11see program in Fig. 3.11 ProsPros
Easy to customize subroutines ‘on the fly’Easy to customize subroutines ‘on the fly’ book example (p. 134)book example (p. 134)
print integers in different basesprint integers in different bases base = non-local (dynamic) referencebase = non-local (dynamic) reference
Binding of referencing Binding of referencing environmentsenvironments
WHEN scope rules should be applied?WHEN scope rules should be applied? usually no problem (just apply the scope rules)usually no problem (just apply the scope rules) problematic case: references to subroutinesproblematic case: references to subroutines
e.g. function parameterse.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 used?when the referred routine is used?
In other wordsIn other words WHAT is the referencing environment of a WHAT is the referencing environment of a
subroutine reference?subroutine reference? recall: there may be multiple instances due recall: there may be multiple instances due
recursionrecursion
Shallow & deep bindingShallow & deep binding
Consider example of Fig. 3.16 (dynamic scoping)Consider example of Fig. 3.16 (dynamic scoping) print_routineprint_routine
should create its environment just before it’s usedshould create its environment just before it’s used otherwise the ‘format trick’ would not workotherwise the ‘format trick’ would not work this late binding is called this late binding is called shallow bindingshallow binding default in dynamically scoped languagesdefault in dynamically scoped languages
older_thanolder_than is designed to use the global is designed to use the global threshold threshold variablevariable i.e. it is meant to be used in that one and only i.e. it is meant to be used in that one and only
environmentenvironment referencing environmentreferencing environment
should be bound when should be bound when older_than older_than is passed as a parameteris passed as a parameter and used when it is finally calledand used when it is finally called
this early binding is called this early binding is called deep bindingdeep binding
Implementing deep bindingImplementing deep binding
Subroutine Subroutine closureclosure bundles together bundles together pointer to subroutine code and it’spointer to subroutine code and it’s referencing environmentreferencing environment
Dynamic scoping & a binding stackDynamic scoping & a binding stack current top of stack defines the environmentcurrent top of stack defines the environment
lookup table case is more complicated (see p. 138)lookup table case is more complicated (see p. 138) when a routine is passed as a parameterwhen a routine is passed as a parameter
save current top of the stack in the closure & pass the save current top of the stack in the closure & pass the closureclosure
when the referenced routine is calledwhen the referenced routine is called use the saved pointer as the top of stackuse the saved pointer as the top of stack if other functions are called, grow another ‘top’ for the if other functions are called, grow another ‘top’ for the
stack from this point (requires a list-implemented stack)stack from this point (requires a list-implemented stack)
Deep binding & static scopeDeep binding & static scope
Deep binding is default in static scopeDeep binding is default in static scope shallow binding does not make much senseshallow binding does not make much sense
Does the binding time matter at all?Does the binding time matter at all? generally notgenerally not
name name lexical nesting lexical nesting nesting does no changenesting does no change
recursion complicates the matterrecursion complicates the matter we must find the correct we must find the correct instanceinstance, too, too closure must capture the closure must capture the currentcurrent instance of every instance of every
visible object when the closure is createdvisible object when the closure is created this saved closure is then used when routines are this saved closure is then used when routines are
usedused example in Fig. 3.13example in Fig. 3.13
Some notesSome notes
Binding rules matter (with static scoping) Binding rules matter (with static scoping) onlyonly when we reference objects that are when we reference objects that are not not local local
neitherneither global global hence, irrelevant in hence, irrelevant in
C: no nested structureC: no nested structure Modula-2: only top-level routines can be passed as Modula-2: only top-level routines can be passed as
parametersparameters and in all languages that do not permit passing and in all languages that do not permit passing
subroutines as argumentssubroutines as arguments TK: good programmer doesn’t make such TK: good programmer doesn’t make such
programs anywayprograms anyway
Implementing deep bindingImplementing deep binding
Static links define referencing Static links define referencing environmentsenvironments pass: create closure with current static pass: create closure with current static
linklink callcall
use the saved static linkuse the saved static link instead of creating a new oneinstead of creating a new one
when creating the frame recordwhen creating the frame record static chain is now the same as in the time static chain is now the same as in the time
the parameter was passedthe parameter was passed
Classification of valuesClassification of values
First-class values can beFirst-class values can be passed as parameterspassed as parameters returned from a subroutinereturned from a subroutine assigned to variablesassigned to variables e.g. integers in most languagese.g. integers in most languages
Second-class valuesSecond-class values can only be passed as parameterscan only be passed as parameters e.g. arrays in C/C++e.g. arrays in C/C++
Third-class valuesThird-class values can not even be passed as a parametercan not even be passed as a parameter e.g. jump labels (in most languages that have a goto-e.g. jump labels (in most languages that have a goto-
statement)statement)
Subroutine valuesSubroutine values
First-classFirst-class functional languagesfunctional languages
note: these can even note: these can even create create new subroutinesnew subroutines Modula-2 & -3, Ada 95, C, C++Modula-2 & -3, Ada 95, C, C++
language-specific restrictions on uselanguage-specific restrictions on use
Second-classSecond-class almost all other languagesalmost all other languages Ada 83: third-classAda 83: third-class
Problem with first-class Problem with first-class subroutines...subroutines...
Reference to a subroutineReference to a subroutine may live may live longerlonger than the scope that created it than the scope that created it referencing environment no longer exists referencing environment no longer exists
when routine is calledwhen routine is called Functional languagesFunctional languages
see example on p. 141see example on p. 141 unlimited extentunlimited extent of local objects of local objects frames are allocated from the heap (not stack)frames are allocated from the heap (not stack) garbage collected when no references remaingarbage collected when no references remain
...Problem with first-class ...Problem with first-class subroutinessubroutines
Imperative languages Imperative languages wantwant to use the stack to use the stack limited extentlimited extent of local objects of local objects frames are deleted from the stack when execution leaves the frames are deleted from the stack when execution leaves the
subroutine subroutine dangling references if 1dangling references if 1stst class subroutines are allowed class subroutines are allowed
Algol-family languages have different workaroundsAlgol-family languages have different workarounds Modula-2: only top-level subroutines can be referenced toModula-2: only top-level subroutines can be referenced to Modula-3Modula-3
only top-level subroutines are 1only top-level subroutines are 1stst class, others are 2 class, others are 2ndnd class class Ada 95Ada 95
a nested routine can be returned (by a function) only to a scope a nested routine can be returned (by a function) only to a scope that contains that routinethat contains that routine
referencing environment will always be alivereferencing 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)
Binding within a scopeBinding within a scope
This far we have assumedThis far we have assumed every nameevery name refers to a distinct objectrefers to a distinct object in every scopein every scope
This is not necessarily the case!This is not necessarily the case! aliasing: many names for same thingaliasing: many names for same thing overloading: one name for several overloading: one name for several
thingsthings
AliasingAliasing
AliasAlias extra name for something that already has a name (in extra name for something that already has a name (in
the current scope)the current scope) How are they created?How are they created?
Fortran: explicit declarations (equivalence)Fortran: explicit declarations (equivalence) Pascal, C: variant/union structuresPascal, C: variant/union structures pointerspointers reference parameters (esp. with non-locals combined)reference parameters (esp. with non-locals combined)
They are usually considered bad becauseThey are usually considered bad because they create confusion and hard-to-track errors (Fig. 3.14)they create confusion and hard-to-track errors (Fig. 3.14) compilers can optimize better if they know there’s no compilers can optimize better if they know there’s no
aliasingaliasing see example on p. 143see example on p. 143
OverloadingOverloading
one name for several objects in the same one name for several objects in the same scopescope
most programming languages support at least most programming languages support at least some overloadingsome overloading esp. arithmetic operationsesp. arithmetic operations
semantic rulessemantic rules define which binding to usedefine which binding to use context of the name must give enough information context of the name must give enough information
to resolve the binding (see Fig. 3.15)to resolve the binding (see Fig. 3.15) implicit or explicit (see Ada example on p. 144)implicit or explicit (see Ada example on p. 144)
Overloading of ...Overloading of ...
Enumeration constantsEnumeration constants Ada example in Figure 3.15Ada example in Figure 3.15
dec & oct overloadeddec & oct overloaded print has not sufficient context print has not sufficient context explicit qualification explicit qualification
requiredrequired Modula-3: each occurrence must be qualifiedModula-3: each occurrence must be qualified
SubroutinesSubroutines Ada, C++Ada, C++
arbitrary number as long as parameter types/number arbitrary number as long as parameter types/number are differentare different
also arithmetic operators (syntactic sugar)also arithmetic operators (syntactic sugar) Figure 3.16Figure 3.16
Overloading is NOT coercionOverloading is NOT coercion
CoercionCoercion process in which the compiler process in which the compiler automaticallyautomatically
converts an object X:T1 to another type T2converts an object X:T1 to another type T2 when X is used in a context where T2 is expectedwhen X is used in a context where T2 is expected
in overloadingin overloading separate functions are selected by the compiler separate functions are selected by the compiler
for different usesfor different uses in coercionin coercion
there is only one functionthere is only one function compiler makes the necessary type compiler makes the necessary type
transformationstransformations
Overloading is NOT Overloading is NOT polymorphismpolymorphism
PolymorphismPolymorphism polymorphic objects may represent objects of polymorphic objects may represent objects of
more than one typemore than one type subroutines can manipulate their polymorphic subroutines can manipulate their polymorphic
parameters without any conversionsparameters without any conversions that is, they are not coerced to anything elsethat is, they are not coerced to anything else
How is this possible?How is this possible? all objects have some common characteristicsall objects have some common characteristics
and only these are used (inheritance makes this sure)and only these are used (inheritance makes this sure) objects contain other information so the objects contain other information so the
subroutine can customize itself appropriatelysubroutine can customize itself appropriately e.g. to find the correct version of the inherited methode.g. to find the correct version of the inherited method
Examples of polymorphismExamples of polymorphism
abs(x) for any type that supportsabs(x) for any type that supports comparison ‘> 0’ andcomparison ‘> 0’ and negationnegation
counting the length of a list (of any type)counting the length of a list (of any type) only succ & empty –tests requiredonly succ & empty –tests required
mergesortmergesort comparison, succ, empty, conscomparison, succ, empty, cons
conformant array parametersconformant array parameters very limited form of polymorphism (Pascal, very limited form of polymorphism (Pascal,
Ada)Ada)
Overloading is NOT genericsOverloading is NOT generics
Generic subroutines (or modules)Generic subroutines (or modules) parameterizedparameterized templates templates that can be that can be instantiatedinstantiated to to
create create concreteconcrete subroutines subroutines early C++ versions used cpp to do thisearly C++ versions used cpp to do this
Ada example in Fig. 3.17Ada example in Fig. 3.17 Book defines generics as Book defines generics as parameterized parameterized
polymorphismpolymorphism polymorphic routine is a polymorphic routine is a singlesingle object capable of accepting object capable of accepting
multiple typesmultiple types compiled to a single body of codecompiled to a single body of code
generic routines are instantiated to create an own generic routines are instantiated to create an own concrete routine for each different useconcrete routine for each different use
compiled to several copies of the codecompiled to several copies of the code Ada allows these instance names to be overloadedAda allows these instance names to be overloaded C++ requires them to do soC++ requires them to do so