Dynamic scope rules determine that bindings depend on the current state of program execution and the most recent active binding made at run time, rather than where variables are declared. This means references cannot always be resolved at compile time. Dynamic scope was common in early Lisp dialects and complicates type checking. When a procedure is called within another procedure, dynamic scope uses the most recent binding, while static scope uses the binding at declaration.
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0 ratings0% found this document useful (0 votes)
56 views8 pages
Dynamic Scope Rule: Example 1
Dynamic scope rules determine that bindings depend on the current state of program execution and the most recent active binding made at run time, rather than where variables are declared. This means references cannot always be resolved at compile time. Dynamic scope was common in early Lisp dialects and complicates type checking. When a procedure is called within another procedure, dynamic scope uses the most recent binding, while static scope uses the binding at declaration.
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 8
dynamic scope rule
bindings depend on the current state of program execution
– They cannot always be resolved by examining the program because they are dependent on calling sequences – To resolve a reference, we use the most recent, active binding made at run time – Dynamic scope rules are usually encountered in interpreted languages – early LISP dialects assumed dynamic scope rules. – Such languages do not normally have type checking at compile time because type determination isn't always possible when dynamic scope rules are in effect Example 1 program scopes (input, output ); var a : integer; procedure first; begin a := 1; end; procedure second; var a : integer; begin first; end; begin a := 2; second; write(a); end. • Static scope rules require that the reference resolve to the most recent, compile-time binding, namely the global variable a • Dynamic scope rules, on the other hand, require that we choose the most recent, active binding at run time • At run time we create a binding for a when we enter the main program. • Then we create another binding for a when we enter procedure second • This is the most recent, active binding when procedure first is executed • Thus, we modify the variable local to procedure second, not the global variable • However, we write the global variable because the variable a local to procedure second is no longer active • Example 2 1. n : integer – – global declaration 2. procedure first 3. n := 1 4. procedure second 5. n : integer – – local declaration 6. first() 7. n := 2 8. if read integer() > 0 9. second() 10. else 11. first() 12. write integer(n) The Meaning of Names within a Scope Aliases In C, C++, and some other programming languages, the term aliasing refers to a situation where two different expressions or symbols refer to the same object. When references access that object in different ways—as both reads and stores—there are consequences for the order in which these mixed accesses can happen. – What are aliases good for? • space saving - modern data allocation methods are better • multiple representations - unions are better • linked data structures - legit – Also, aliases arise in parameter passing as an unfortunate side effect • Euclid scope rules are designed to prevent this • Consider the following example: double sum, sum_of_squares; … void accumulate(double& x) { sum += x; sum_of_squares += x * x; } … accumulate(sum); • Easy to make a mistake by passing something accidentally. • Somewhat common error, which is why some languages moved to making subroutines closed scopes. Explicit import lists allow the compiler to detect when an alias is being created. • If sum is passed as an argument to accumulate, then sum and x will be aliases for one another, and the program will probably not do what the programmer intended. This type of error was one of the principal motivations for making subroutines closed scopes in Euclid and Turing int a, b, *p, *q; ... a = *p; /* read from the variable referred to by p */ *q = 3; /* assign to the variable referred to by q */ b = *p; /* read from the variable referred to by p */ Overloading Overloading allows different methods to have the same name, but different signatures where the signature can differ by the number of input parameters or type of input parameters or both. Overloading is related to compile-time (or static) polymorphism – some overloading happens in almost all languages • integer + v. real + • read and write in Pascal • print in Python – some languages get into overloading in a big way • Ada • C++ (and hence Java and C#) • It's worth distinguishing between some closely related concepts – overloaded functions - two different things with the same name; in C++ • overload norm int norm (int a){return a>0 ? a : -a;) complex norm (complex c ) { // ... – polymorphic functions -- one thing that works in more then one way • Code takes a list of types, where the types have some commonality that will be exploited. • Used in Ada and smalltalk, primarily – It's worth distinguishing between some closely related concepts (part 2) – generic functions: a syntactic template that can be instantiated in more than one way at compile time. • via macro processors in C++ • built-in in C++ - remember templates? • in Clu • in Ada The Binding of Referencing Environments • Accessing variables with dynamic scope: – (1) keep a stack (association list) of all active variables • When you need to find a variable, hunt down from top of stack • This is equivalent to searching the activation records on the dynamic chain • Accessing variables with dynamic scope: – (2) keep a central table with one slot for every variable name • If names cannot be created at run time, the table layout (and the location of every slot) can be fixed at compile time • Otherwise, you'll need a hash function or something to do lookup • Every subroutine changes the table entries for its locals at entry and exit. • REFERENCING ENVIRONMENT of a statement at run time is the set of active bindings • A referencing environment corresponds to a collection of scopes that are examined (in order) to find a binding • SCOPE RULES determine that collection and its order • BINDING RULES determine which instance of a scope should be used to resolve references when calling a procedure that was passed as a parameter they govern the binding of referencing environments to formal procedures