Basic Semantics Chapter 5 of Louden covers the
Basic Semantics • Chapter 5 of Louden covers the basic elements that are used to construct the meaning of a program. • No matter what kind of definition is provided for a programming language, it must be based on some simple concepts that every programmer can understand • These concepts include names, bindings, attributes, the lifetime and extent of names, indirect references to objects (pointers), and storage management. Lecture #14 PLP Spring 2004, UF CISE 1
Names, Attributes, and Bindings • • • A name is used to denote some entity. A name has an extent (the context in which the name has a certain meaning) and a lifetime (a period of time during which the meaning is valid). Programming languages also deal with values representing things, and locations in which values can be stored. Each name has associated attributes. Consider the C declaration const int n = 5; which associates several attributes with the name n, namely, its storage class (constant), its type (int), and its value (5). In this declaration int x = 5; the type and initial value are associated with the name x. A definition of a function in C double square(double x) { return x*x; } associates a type with the function square that gives – the number, names, and types of its arguments – its return type and – the code that must be executed when the function is called. Lecture #14 PLP Spring 2004, UF CISE 2
Binding Time • Attributes can be bound to names at different times. – Static Binding: the attribute is bound before the program is executed. – Dynamic Binding: the attribute is bound at run time. • We can further subdivide these times as follows: – – – Language definition time Language implementation time Translation time Link time Load time Execution time Lecture #14 PLP Spring 2004, UF CISE 3
Representing Name Attributes (Semantic Functions) • A semantic function is a function that gives meaning to names. The domain of a semantic function is a set of names, the range is the set of meanings (however you may define that term). • Symbol tables, program environments, and memory each represent a different type of semantic function. • Symbol tables are used by compilers and interpreters to store all attributes of names relevant to the translation of a program. • A program’s environment is the collection of elements that are used at run-time to bind names to their locations (or other relevant attributes in an interpreter). • The memory of a computer is used to map locations to their associated values. Lecture #14 PLP Spring 2004, UF CISE 4
Declarations • A declaration is a statement of fact concerning a name. Declarations establish bindings. • Some declarations are explicit, others are implicit: int x; int x = 0; • FORTRAN provided implicit type declarations for variables based on their initial letter (i-n: integer, everything else: real). • C/C++ nomenclature: a definition binds all statically declarable properties of a name. • Partial declarations are typically necessary in languages that use normal vs. pointer semantics in order to be able to define recursive types. (One must be able to declare an instance variable to be a pointer to the type of object being declared. ) • For mutually recursive types, one of the names has yet to be introduced: class C; class D { C *cref; … }; class C { D *dref; … }; Lecture #14 PLP Spring 2004, UF CISE 5
Declaration Contexts • Declarations appear in some program context, and programming languages typically introduce specific contexts for collecting together a set of declarations. Algol 60 introduced the idea of using such a block as a way of providing program structure. • Different languages use different linguistic elements to identify blocks (Pascal begin/end, C braces) • Most languages containing block allow them to be nested: { double w; double x; … { int y; int z; … } } • In block structured languages, names are accessible only within the block in which they are declared. That is, their scope (extent) is lexically determined. This gives rise to what is known as lexical or static scope (because the program lexical structure—its text—can be analyzed statically to determine what bindings are available to any program statement). Lecture #14 PLP Spring 2004, UF CISE 6
Scope Diagrams int x; void p(void) { char y; … } /* p */ void q(void) { double z; … } /* q */ main() { int w[10]; … } Lecture #14 y z p x q w main PLP Spring 2004, UF CISE 7
Shadowing Scope Holes • The previous diagram showed the concept of visibility but left out the concept of shadowing, in which a name is declared in an inner scope. The inner declaration hides (or casts a shadow over) the outer declaration, introducing a scope hole, a hole in the scope region of the outer variable. int x; void p(void) { double x; x = 2. 0; … } main() { x = 2; … } Lecture #14 scope of outer x scope of inner x PLP Spring 2004, UF CISE 8
Other Controls on Extent • In the last class we touched on the idea of using of classes, namespaces, modules, and other grouping constructs for controlling access/visibility of names. • C/C++ overload the storage class static to provide programmers with the capability of restricting visibility of a name to the file in which that name is declared. If a variable is declared with global scope (outside a function) and it is not declared to be static, other files can access the name by providing an extern declaration. • In some dynamic languages in which declarations need not appear at the beginning of a block, variables may be quasi-statically scoped in blocks corresponding to loops. That is, an outer declaration may prevail until a declaration or assignment of the variable is encountered within the loop. At that time, a scope hole for the outer name is introduced. Lecture #14 PLP Spring 2004, UF CISE 9
- Slides: 9