Access To Nonlocal Names in Compiler Design
In this article you will learn in details Access To Nonlocal Names in Compiler Design so read article.
It is critical to understand how procedures access their data, especially the mechanism for locating data that is used within a procedure p but is not part of p. In languages where procedures can be declared within other procedures, access becomes more complicated.
As a result, we start with C functions and then add ML, a language that allows for both nested function declarations and functions as “first-class objects,” meaning that functions can take functions as arguments and return functions as values. This functionality can be activated by altering the run-time stack’s implementation.
Data Access without Nested Procedures: Access To Nonlocal Names in Compiler Design
All variables in the C programming language are defined either within a single function or outside of any function (“globally”). Most notably, declaring one procedure whose scope is entirely contained within another procedure is unlikely. Rather, a global variable v has a scope that includes all functions that follow the declaration of v, except where the identifier v is defined locally.
Variables declared within a function have a scope that is limited to that function or a subset of it, depending on whether the function has nested blocks, as discussed in Section 1.6.3. The allocation of storage for variables and access to those variables is easy in languages that do not allow nested procedure declarations:
- Static storage is assigned to global variables. These variables’ positions remain constant and are known at compile time. We simply use the statically defined address to access an attribute that is not local to the currently executing procedure.
- Every other name must be exclusive to the top-of-the-stack activation. The top pointer of the stack can be used to access these variables.
Declared procedures may be passed as parameters or returned as results (in C, a pointer to the method is passed) with no significant change in the data-access strategy when using static allocation for globals. Without nested procedures and the C static-scoping law, any name that is not local to one procedure is nonlocal to all procedures, regardless of how they are enabled. If a procedure is returned as a result, every nonlocal name refers to the storage that has been statically allocated for it.
Issues with Nested Procedures: When a language allows procedure declarations to be nested while still using the usual static scoping rule, access becomes even more complicated; that is, a procedure can access variables of procedures whose declarations surroundits own declaration, following the nested scoping rule defined for blocks in Section 1.6.3.
The explanation for this is that understanding that p’s declaration is immediately nested within q at compile time does not tell us where their activation records will be at run time. In reality, since either p or q, or both, may be recursive, there may be several p and/or q activation records on the stack.
In a nested method, find the declaration that refers to a nonlocal name x. p is a static decision that can be implemented using a block-specific extension of the static-scoperule. Assume that the enclosing method q declares x. Finding the relevant activation of q from an activation of p is a dynamic decision that necessitates the use of additional run-time activation information. The use of “access ties” is one potential solution to this issue.
Nested Procedure Declarations in a Language: We introduce a language that supports nested procedures since the C family of languages and many other well-known languages do not. Nested procedures have a long background in programming languages. Algol 60, a forerunner of C, and its descendant Pascal, a once-popular teaching language, both had this capability. One of the most influential later languages with nested procedures is ML, and it is this language’s syntax and semantics that we will borrow (see the box “More about ML” for some of ML’s interesting features):
ML is a functional language, which means that variables are not modified until they have been declared and initialised. Only a few exceptions exist, such as the list, which can have its elements modified using special function calls.
A declaration of the form: defines variables and initialises their unchangeable values.
val (name) = (expression)
Functions are defined using the syntax:
fun (name) ( (arguments) ) = (body)
For function bodies we shall use let-statements of the form:
let (list of definitions) in (statements) end
Normally, the definitions are v a l or fun statements. The meaning of any such definition includes all subsequent definitions up to and including the in, as well as all statements up to and including the end. Function descriptions may be nested, which is particularly useful. A let-statement in the body of a function p, for example, may include the description of another (nested) function q. Similarly, q may have function meanings within its own body, allowing for function nesting to be as deep as desired.
Read More –
- Storage Allocation in Block Structured Language
- Reading Initialization Parameters in Servlets
- SLR Parsing Table Construction Example
- Path with Maximum Sum in a Triangular Pattern
- Access To Nonlocal Names in Compiler Design