Object closures

Object oriented languages allow implementers to define object closures, function objects, or functors to pass referencing environment with objects. Can let the object’s fields hold context for the method.

Ex1: Java’s interface allows the programmer to encapsulate routines as methods of objects, e.g., “runnable” objects Ex2: In C++, an object of a class that overrides operator() can be called as if it were a function!

Lambda Expressions

Generally, the lambda keyword introduces an anonymous function; this comes from the lambda calculus, which provides the mathematical foundations for functional programming. Will be discussed later in the course (Scott section 3.6.4).

Meaning of names within a scope

  • aliases: two or more names that refer to the same object at the same point in the program
  • Overloaded name: A name that can refer to more than one object at a given point in a program
  • Overloading re: polymorphism: allows a subroutine or a program fragment to behave in a different way depending on the type of its args

Aliases

Ex: union in C:

union Data {
	int i;
	double d;
} my_data;

my_data can either store an int or double; in memory, storage for largest possible type is required to be allocated.

Aliases are common sources of bugs and code analysis becomes more difficult.

Overloading

Ex: Almost all programming languages have the ‘+’ operator overloaded for different arg types.

Polymorphism

  • Explicit polymorphism-code takes type as a parameter. Also called genericity.
  • Subtype polymorphism-subtype relation between types. Supports dynamic dispatch (method overriding by subtypes). More on this later.

Coercion

Compiler automatically converts a value from one type to another when second type is required by context.

Difference between coercion and overloading:

int i = 4;
int j;
j = 2.3 + i;

The 4 is coerced into a floating point number, and then the correct ‘+’ is chosen via the overloaded floating point args.

Coercion rules are different for different languages!

Chapter 4 - Semantic Analysis

Context constraints

Not specified by CFG; usually too much work to try to specify these constraints via a CFG (hence their context-free-ness)

Kinds of semantic (contextual) constraints- static and dynamic!

Examples of static constraints:

  1. Variables must be declared before used
  2. Variables cannot be declared more than once in the same program unit
  3. Compatible types during declaration
  4. Every function must contain at least one return statement

Static analysis is what’s done to check these constraints. Can be described in terms of decoration of a syntax tree. The annotations themselves are known as attributes. The analysis is precise if the compiler can determine whether a griven program follows the rules.

Dynamic checks consist of code generated by the compiler to catch run-time errors. For example, assert.

Role of semantic analyzer

Wide variation in what must be checked dynamically between programming languages. Static analyzers enforce static rules and annotate the program with information needed to generate code for dynamic checks.

Attribute grammars

Provides a formal framework for decoration of a tree. Based on a context free grammar. Add attributes to various symbols and production rules to semantic rules to specify context constraints.

Semantic funtions must be written in terms of some already existing notation. For ex, normal mathematics (e.g., specifying range for an unsigned int). Also, can use code fragments, type theory, etc.