# Lecture 013

## Semantics

Semantics: what is the actual desired behavior of the code

You can specify the semantics of a language by saying whatever is executed in the byte level is the expected behavior of the code. However, it does not enable code optimization since optimization might sometimes change small details in the exact behavior. So we need to distinguish defined behavior (we guarantee) with undefined behavior (might be optimized out)

If we were to use stack machine to define code behavior: - we might care whether to use stack machine - we might care which way stack grows - we might care how integers are represented - we might care particular instruction set of the architecture

These are too irelevant for an ordinary programmer.

Operational Semantics: describe program evaluation via execution rules on an abstract machine. It is useful for specifying implementations.

Denotational Semantics: program's text is mapped to a function in mathematical sense.

Axiomatic Semantics: define the behavior as @require and @ensure. Foundation of many program verification systems.

### Operational Semantics

In operational semantics

• environment $E$: a mapping between variable name to memory location. Note that we only write environment mappings that is in scope. For example $E = [a : l_1, b : l_2]$

• store $S$: a mapping between memory location to value of the variable. For example: $S = [l_1 \to 5, l_2 \to 7]$

We also define a notation on how we update the store: we write $S' = S[12/l_1]$ to update the value at location $l_1$ to $12$. So we guarantee $S'(l_1) = 12 \land (\forall l \neq l_1)(S'(l) = S(l))$

We also need a way to represent objects: $X(a_1 = l_1, ..., a_n = l_n)$:

• $X$: the class of the object

• $a_i$: the attribute (including the inherited ones)

• $l_i$: the location where $a_i$ exists

Special objects without attributes:

• $Int(5)$: integer with value $5$

• $Bool(true)$: boolean with value true

• $String(4, "Cool")$: string of size 4

• $void$: no operations can be performed on it except for test isVoid(). (or NULL)

self, E, S \vdash e : v, S'

The above is an evaluation judgement: if evaluation of e terminates then the value of e is v and the new store is S'

• self: current value of self object

• E: current variable environment

• S: current store

Notice that the self object and E is not modified. The only side effect of evaluation is the value and updated S'.

Also the expression only guarantee to hold when the evaluation actually terminates.

### Evaluation Rules

Note that in above example, we only evaluate by look up, we are not changing any value.

Note that the order of evaluation matters.

When we wan to allocate new variables to our environment and store, we need to define a new instruction newloc() that allocate an return a new location.

#### Allocation Evaluations

Default Value: for each class $A$ there is a default value $D_A$

• $D_{int} = Int(0)$

• $D_{bool} = Bool(false)$

• $D_{string} = String(0, "")$

• $D_A = void$

For class $A$, we write: $class(A) = (a_1 : T_1 \leftarrow e_1, ..., a_n : T_n \leftarrow e_n)$

• $a_i$: attributes (include inherited in greatest ancester first order)

• $T_i$: type

• $e_i$: initializers

Note that when initializers are evaluated (and typing), only attributes are in scope.

Some error are not caught by type checker can happen run-time:

• dispatch on void

• division by zero

• subtract out of range

• heap overflow

Most language does not have a well specified operational semantics. When portability (heterogeneous device) is important, operational semantics is essential.

Table of Content