Chapter 3 untyped arithmetic expressions
Summary of desirable properties for a system
Determinacy of the single-step evaluation relation.
Should hold for all systems.
Uniqueness of normal-forms.
Should hold for all systems.
Values are normal forms.
Should hold for all systems.
Normal forms are values.
May not hold for all systems.
Termination of evaluation.
May not hold for all systems.
Introduction
The convention used is similar to the standard BNF [cf. Aho, Sethi, and Ullman, 1986].
t ::= terms:
true constant true
false constant false
if t then t else t conditional
0 constant zero
succ t successor
pred t predecessor
iszero t zero testA simple untyped expression language - Untyped calculus of booleans and numbers
Syntactically, this language comprises of:
- The boolean constants
trueandfalse. - Conditional expressions (
ifexpression). - The numeric constant
0. - The arithmetic operators
succ(successor) andpred(predecessor). - A testing operation
iszerothat returns true when it is applied to 0, and false when it is applied to some other number.
- The boolean constants
Abstract syntax notation
Term definition (): The notation declares the set of terms, with the letter (and variants like ) used as a metavariable to range over terms.
Metavariable: is a placeholder for a particular term of the object language, but belongs to the metalanguage (the language used for description).
This concept is borrowed from meta-mathematics, giving rise to the term metatheory (the formal study of a logical system's properties).
The prefix meta- comes from meta-mathematics, the subfield of logic whose subject matter is the mathematical properties of systems for mathematical and logical reasoning.
Metatheory: The collection of true statements that we can make about some particular logical system (or programming language)-and, by extension, the study of such statements.
-> Phrases like "metatheory of subtyping" can be understood as "the formal study of the properties of systems with subtyping".
A program is simply a term built from the forms defined in the grammar.
The symbol is used to display the result of evaluating an example term.
- Example:
if false then 0 else 11.
- Example:
Terms vs expressions:
Currently, term and expression are interchangeable.
Starting in Chapter 8:
- Expression will be used for all syntactic phrases (terms, types, kinds). For calculi with additional syntactic categories such as types, expression is used for all sorts of syntactic phrases (including term expressions, type expressions, kind expressions, etc.)
- Term will be reserved for phrases representing computations (i.e., phrases that can substitute for ).
Values:
- The results of evaluation are terms of a simple form: boolean constants or numbers (nested
succapplications to0). - Values play a special role in formalizing evaluation order.
- The results of evaluation are terms of a simple form: boolean constants or numbers (nested
Abstract vs concrete syntax: Parentheses (e.g., in
iszero(pred(succ 0))) are used for readability but are not part of the grammar's abstract syntax, which is currently unambiguous."Nonsensical" terms:
- The syntax permits terms that are semantically dubious (e.g.,
succ trueorif 0 then 0 else 0). - These terms are what make the simple language interesting, as the goal of the type system is precisely to exclude such ill-formed programs.
- The syntax permits terms that are semantically dubious (e.g.,
Syntax
There are more than one way to describe a syntax of a language.
The BNF notation above.
Inductive definition (more verbose).
The set of terms () is the smallest set such that:
- .
- If , then .
- If , then .
Structure of the definition
- Clause 1 specifies base elements (
true,false,0). - Clause 2 specifies rules for building compound expressions (
succ t1,if t1 then t2 else t3, etc.) from existing terms. - "Smallest set": This crucial phrase ensures that T contains no elements other than those absolutely required by the construction rules in the preceding clauses.
- Clause 1 specifies base elements (
Formally, the definition defines T as a set of trees, not a set of linear strings.
The use of parentheses in written examples (the linear form) serves merely to clarify the underlying tree structure (the abstract syntax) of compound subterms.
2-dimensional inference rule format.
A different shorthand for the same inductive definition of terms.
Commonly used in "natural deduction style" presentations of logical systems.
Each rule is read, "If we have established the statements in the premise(s) listed above the line, then we may derive the conclusion below the line."
The fact that is the smallest set satisfying these rules is often (as here) not stated explicitly.
Inference rule (generic term): The term inference rule is used generically throughout the book to refer to any rule in the system, including both axioms and rules with one or more premises.
Axioms: Rules with no premises (like the first three base cases for true, false, and 0). They are often written without the horizontal bar.
Rule schemas (formal terminology): What are called "inference rules" are technically rule schemas because their premises and conclusions contain metavariables (
t1,t2, etc.).- Each schema formally represents an infinite set of concrete rules that are obtained by consistently replacing the metavariables with all possible phrases from the appropriate syntactic category (e.g., replacing t with every possible term).
Concrete generator notation.
- More "concrete" style that gives an explicit procedure for generating the elements of .
Exercise 3.2.4
Task: How many elements does have?
Solution
Take for any .
Then, .
- .
- .
- .
Exercise 3.2.5
Task. Show that the sets are cumulative-that is, that for each we have .
Solution
- It's obvious that .
- Suppose that for some .
Then:
Therefore, .
- The inductive definition and inference rule format characterize the set as the smallest set satisfying certain "closure properties".
- The concrete generator notation shows how to actually construct the set as the limit of a sequence.
- Proof that the inductive definition/inference rule format produce the same language as the concrete generator notation.
Proposition: .
Because is the smallest set satisfying certain conditions, it suffices to show that:
- satisfies these conditions.
- Any set satisfying the conditions has as a subset (i.e., that is the smallest set satisfying the conditions).
- ( is the smallest set)
The goal is to show that is a subset of (i.e., ).
- This part checks that satisfies the three conditions in Definition 3.2.1.
- Constants: It is clear that the constants are in . Since is closed under the structural rules, the constants are in .
- Unary operators: By the definition of , if , then . But since is closed under the
succrule, then must also be in . The same applies to and . - Ternary operator: Similarly, if , then is in , and by the closure of under the
ifrule, it must be in . - Since satisfies the three conditions in Definition 3.2.1, and is defined to be the set of elements formed by repeated application of these conditions (hence for any set satisfying the conditions), it follows immediately that .
- (using complete induction)
The goal is to show that is a subset of (i.e., ).
- This part uses complete induction on to argue that every set is a subset of (a set satisfying the three conditions).
- Let be the smallest set satisfying the three conditions (i.e., ).
- Base case: For , . Since trivially, the base case holds.
- Inductive case: Suppose for all (or if we let the induction proceed on ). We must show that .
- Any element of must come from one of the following three sets of possibilities (corresponding to the definition of ):
- If is a constant (, , or ), then by condition 1.
- If has the form , , or , then . By the induction hypothesis, . Since satisfies condition 2 (closure under constructors), .
- If has the form , then . By the induction hypothesis, . Since satisfies condition 3 (closure under the
ifconstructor), .
- Thus, we have shown that each . By the definition of as , this completes the argument that .
- Insight
- It is worth noting that the proof uses complete induction on the natural numbers , which is not the more familiar "base case/induction case" form.
- In complete induction, one proves that the desired predicate holds for all numbers strictly less than and uses that to prove that it holds for .
- In essence, every step here is an induction step; the only thing that is special about the case where is that the set of smaller values of for which the induction hypothesis can be invoked happens to be empty.
- The same remark will apply to most induction proofs throughout the book, particularly proofs by "structural induction".
Induction on terms
The explicit characterization of the set of terms in Proposition 3.2.6 justifies an important principle for reasoning about its elements based on its structure.
If , then one of three things must be true about :
is a constant.
has the form , , or for some smaller term .
has the form for some smaller terms , and .
-> This observation can be applied in 2 ways:
- Inductive definitions of functions can be given over the set of terms.
- Inductive proofs of properties of terms can be given.
-> Structural induction.
The set of constants appearing in a term , written , is defined as follows:
| Term | definition |
|---|---|
The size of a term , written , is defined as follows:
| Term | definition |
|---|---|
That is, the size of is the number of nodes in its abstract syntax tree.
The depth of a term , written , is defined as follows:
| Term | definition |
|---|---|
Equivalently, is the smallest such that , according to Definition 3.2.3.
Lemma: The number of distinct constants
Statement. The number of distinct constants in a term is no greater than the size of (i.e., ).
Proof
By induction on the depth of .
Assuming the desired property for all terms smaller than , we must prove it for itself.
There are three cases to consider:
Case: is a constant
- Immediate: .
Case:
- By the induction hypothesis, .
- We now calculate as follows:
Case:
- By the induction hypothesis, , , and .
- We now calculate as follows:
General reasoning principle - Generalization of the previous lemma's proof structure
Theorem [Principles of induction on terms]: Suppose is a predicate on terms.
Induction on depth:
If, for each term , given for all such that , we can show , then holds for all .
Induction on size:
If, for each term , given for all such that , we can show , then holds for all .
Structural induction:
If, for each term , given for all immediate subterms of we can show , then holds for all .
Proof
TODO
Semantic styles
How to formulate the semantics of a language precisely?
Three basic approaches to semantics formalization:
Operational semantics
Idea: Define a simple abstract machine for the language.
Abstract: The machine directly ses the terms of the language as its machine code.
State of the machine: For simple languages, it's just a term.
Transition function: Describe the machine's behavior - for each state, either:
- Gives the next state by performing a step of simplification on the term.
- Declares that the machine has halted.
The meaning of a term can be taken to be the final state that the machine reaches when started with as its initial state.
It is sometimes useful to give two or more different operational semantics for a single language:
Some more abstract, with machine states that look similar to the terms that the programmer writes.
Others closer to the structures manipulated by an actual interpreter or compiler for the language.
-> Proving that the behaviors of these different machines correspond in some suitable sense when executing the same program amounts to proving the correctness of an implementation of the language.
Denotational semantics
More abstract.
The meaning of a term: Some mathematical object (number/function) rather than a sequence of machine states.
Giving denotational semantics for a language:
Find a collection of semantic domains.
Define an interpretation function mappings terms into elements of these domains.
-> Domain theory: Facilitate the search for appropriate semantic domains for modeling various language features.
Major advantages of denotational semantics:
Abstracts from the gritty details of evaluation.
Highlights the essential concepts of the language.
The properties of the chosen collection of semantic domains can be used to derive powerful laws for reasoning about program behaviors.
- Laws for proving that two programs have exactly the same behavior.
- Laws for that a program's behavior satisfies some specification.
From the properties of the chosen collection of semantic domains, it is often immediately evident that various (desirable or undesirable) things are impossible in a language.
Axiomatic semantics
- Idea: Define a language by its proof rules/laws, rather than by first defining how programs run (operational) or what they denote mathematically (denotational) and then deriving laws.
- So the "meaning" of a program/term is whatever properties you can prove about it using the axioms and inference rules.
- Strength: Centers the whole story on reasoning about programs, which led to key techniques like invariants.
A bit of history & comparison
1960s-1970s: Operational semantics was often seen as inferior to denotational and axiomatic semantics-okay for "quick and dirty" feature definitions, but viewed as less elegant and less mathematically strong.
1980s shift: Denotational/axiomatic approaches ran into tougher technical issues (denotational: nondeterminism & concurrency; axiomatic: procedures), making operational semantics' simplicity + flexibility more appealing.
Key developments that boosted operational semantics:
Structural operational semantics (SOS) [Plotkin, 1981]
Natural semantics [Kahn, 1987]
CCS [Milner, 1980; 1989; 1999]
These introduced cleaner formalisms and helped transfer techniques from denotational semantics into operational settings.
Today: Operational semantics is a major research area and often the default method for defining languages and proving properties.
Evaluation
Operational semantics of boolean expressions
Three sections in the definition above.
The set of terms.
The set of values, a subset of terms (possible final results of evaluation).
-> Just constants
trueandfalse.-> The meta variable
vis often used.The inference rules for the evaluation relation.
- Written .
- Pronounced " evaluates to in one step".
- Intuition: If is the state of the abstract machine at a given moment, then the machine can make a step of computation and change its state to .
- This relation is defined by three inference rules (or, if you prefer, two axioms and a rule, since the first two have no premises).
What the evaluation rules do not say is just as important as what they do say.
The constants
trueandfalsedo not evaluate to anything, since they do not appear as the left-hand sides of any of the rules.There is no rule allowing the evaluation of a
then- orelse-subexpression of anifbefore evaluating theifitself.The set of evaluation rules, taken together forces a specific evaluation order (strategy).
- Congruence rule = "where to evaluate next" (it propagates evaluation into a subterm; it sets the strategy/order).
- Computation rule = "the actual reduction" (they perform the meaningful work once the guard is a value).
Intuition formalization
Instance of an inference rule: ****An instance of an inference rule is obtained by consistently replacing each metavariable by the same term in the rule's conclusion and all its premises (if any).
Rule satisfied by a relation: A rule is satisfied by a relation if, for each instance of the rule, either the conclusion is in the relation or one of the premises is not.
What does this mean? (ChatGPT)
Setup
- A rule has premises and a conclusion.
- An instance of a rule = a concrete version after substituting its metavariables.
- A relation
R= a set of judgments you consider "true" (e.g.,e \to e', or\Gamma \vdash e : \tau).
Definition
A rule instance
Premises:
P1, P2, ..., PnConclusion:
Cis satisfied by a relation
Riff:either
C \in Ror at least one premise is missing from
R(i.e.,Pi \notin Rfor somei)In words:
You can't have all the premises in R while the conclusion is not in R.
Equivalent logical form
Closure form
If all premises are in
R, then the conclusion must be inR.(P1 \in R \wedge ... \wedge Pn \in R) \Rightarrow (C \in R)"No counterexample" form
There is no rule instance where all premises are in
Rbut the conclusion is not.\neg((P1 \in R \wedge ... \wedge Pn \in R) \wedge (C \notin R))
Operational semantics intuition (small-step)
If the rule is:
Premise:
e1 \to e1'.Conclusion:
e1 e2 \to e1' e2.Then "
Rsatisfies the rule" means: Whenevere1 \to e1'is inR,e1 e2 \to e1' e2must also be inR.Satisfying a rule = being closed under that rule.
One-step evaluation relation
\to: The\tois the smallest binary relation on terms satisfying all the inference rules. When the pair is in the evaluation relation, we say that "the evaluation statement (or judgment) is derivable."Why "smallest"?
Statement is derivable iff it is justified by the rules:
- Either it is an instance of one of the axioms.
- Else it is the conclusion of an instance of rule whose premise is derivable.
The derivability of a given statement can be justified by exhibiting a derivation tree.
Example
The derivability of:
is witnessed by the following derivation tree:
- The bottom is the root.
- The top are the leaves.
An evaluation statement is derivable iff there is a derivation tree with as the label at its root.
-> Often useful when reasoning about properties of the evaluation relation.
-> A proof technique: induction on derivations.
Induction on derivations
TIP
The main idea is to perform induction on the size of the derivations.
At each step of the induction:
- Assume the target property holds for all smaller derivations.
- Perform a case analysis of the evaluation rule used at the root of the derivation.
-> We're looking at a single step of evaluation.
Theorem: Determinacy of one-step evaluation
Problem. If and , then .
Proof
- Induction on a derivation of .
- At each step of the induction, assume the desired result for all smaller derivations.
- Proceed by a case analysis of the evaluation rule used at the root of the derivation.
- Consider the last rule used in the derivation of .
E-IfTrue
-> has the form , where .
-> The last rule in the derivation of cannot be E-IfFalse since we cannot have both and .
-> The last rule in the second derivation cannot be E-If either, since the premise of this rule demands that for some , but does not evaluate to anything.
-> The last rule in the second derivation can only be E-IfTrue, and it immediately follows that .
E-IfFalseE-If
-> has the form , where for some .
Symmetrically, the last rule in the derivation of can only be E-If, which tells us that has the form (which we already know) and that for some .
-> Now the induction hypothesis applies.
TIP
This should hold for most systems.
Exercise 3.5.5
Problem. Spell out the induction principle used in the preceding proof, in the style of Theorem 3.3.4.
Solution
For a derivation , take to be the largest length from the root to a leaf in the derivation.
Induction on derivation:
If, for each derivation , given for all such that , we can show , then holds for all .
Normal form
The final value of computation is particularly interested - states in which the machine cannot take a step.
A term is in normal form if no evaluation rule applies to it- i.e., if there is no such that .
(We sometimes say " is a normal form" as shorthand for " is a term in normal form.")
Theorem: Value is in normal form
Statement. Every value is in normal form.
- Trivial theorem for the current system.
- In most systems, this theorem should hold - otherwise, the language is simply broken.
- Being in normal form is part of what it is to be a value (i.e., a fully evaluated result).
TIP
This should hold for most systems.
Theorem: Normal form implies value
Statement. If is in normal form, then is a value.
Proof
Suppose is not a value.
We show by structural induction that is not in normal form.
Because is not a value, must have the form for some , , .
- If or , it's obvious that is not in normal form because we can use
E-IfTrueorE-IfFalse. - If is neither nor , then it is not a value.
-> The induction hypothesis applies, is not a normal form. Then is not in normal form because we can use E-If.
WARNING
This does not hold for most systems.
Multi-step evaluation relation
- The multi-step evaluation relation is the reflexive, transitive closure of one-step evaluation.
Exercise 3.5.10
Problem. Rephrase Definition 3.5.9 as a set of inference rules.
Solution
This one uses the inductive definition style instead of inference rules format because they are similar and inductive definition can be written more easily in Notion.
is the smallest set such that:
- For every term , .
- For every term , , if then .
- For every term , , , if and then .
Theorem: The uniqueness of normal form
Statement. If and , where and are both normal forms, then .
Proof
Follow directly from determinacy of single-step evaluation relation.
TIP
This should hold for most systems.
Theorem: Termination of evaluation
Statement. For every term there is some normal form such that .
Proof
- Each evaluation step reduces the size of the term.
- The size is a termination measure because the usual order on the natural numbers is well founded.
WARNING
This does not hold for most systems.
Exercise 3.5.13
Statement 1. Suppose we add a new rule:
to the ones in Figure 3-1. Which of the above theorems (3.5.4, 3.5.7, 3.5.8, 3.5.11, and 3.5.12) remain valid?
Solution
- Theorem - Determinacy of one-step evaluation
[x] No longer valid.
Counterexample:
Applying
E-Funny1, . - ApplyingE-IfTrue, .Theorem - Value is in normal form
Still valid.
- Theorem - Normal form implies value
Still valid.
- Theorem - The uniqueness of normal forms
[x] No longer valid.
Counterexample: Same as Determinacy of one-step evaluation
- Theorem - Termination of evaluation
Still valid.
Statement 2. Suppose instead that we add this rule:
Now which of the above theorems remain valid? Do any of the proofs need to change?
Solution
- Theorem - Determinacy of one-step evaluation
Still valid.
This proof should change.
- Theorem - Value is in normal form
Still valid.
This proof doesn't need to change.
- Theorem - Normal form implies value
Still valid.
The proof doesn't need to change.
- Theorem - The uniqueness of normal forms
Still valid.
This proof should change.
- Theorem - Termination of evaluation
Still valid.
This proof should change (a bit).
Evaluation - Arithmetic expressions
Operational semantics of arithmetic expressions - An extension of boolean expressions above
A new syntactic category of numeric values.
The final result of evaluating an arithmetic expression can be a number, where a number is either or the successor of a number. (but not the successor of an arbitrary value: we will want to say that is an error, not a value).
Note that in
E-PredSucc, only numeric values are allowed.-> .
-> This is prohibited to preserve the determinacy of one-step evaluation.
The unique next step.
Exercise 3.5.14 - Determinacy of one-step evaluation
Statement. Show that Theorem 3.5.4 is also valid for the evaluation relation on arithmetic expressions: if and , then .
Proof
This only considers the subset of arithmetic expressions.
Perform induction on a specific derivation .
Assume that this holds for all smaller derivations.
- Consider the last rule applied to obtain .
E-Succ
In this case, and such that .
Then, must also be obtained from E-Succ as well, because there's no other rules that allow to be in the form of .
Therefore, such that .
By induction hypothesis, it holds true for this case.
E-PredZero
In this case, and .
So, the potential rules that can generate are E-PredZero, E-PredSucc or E-Pred.
E-PredSucc cannot generate because then, must be in the form of .
E-Pred cannot generate because is a normal form.
E-PredZero is trivial.
E-PredSuccE-PredE-IsZeroZeroE-IsZeroSuccE-IsZero
Stuck terms
A closed term is stuck if it is in normal form but not a value.
-> "Stuckness" represents a simple notion of run-time error for our simple machine.
-> Stuckness characterizes the situations where the operational semantics does not know what to do because the program has reached a "meaning-less state."
-> In a more concrete implementation of the language, these states might correspond to machine failures of various kinds: segmentation faults, execution of illegal instructions, etc.
-> All these kinds of bad behavior are collapsed into the single concept of "stuck state."
Exercise 3.5.16 - Explicit failure state in operational semantics
Statement.
A different way of formalizing meaningless states of the abstract machine is to:
- Introduce a new term called .
- Augment the operational semantics with rules that explicitly generate in all the situations where the present semantics gets stuck.
To do this in detail, we introduce 2 new syntactic categories:
and we augment the evaluation relation with the following rules:
Show that these 2 treatments of run-time errors agree by:
- Finding a precise way of stating the intuition that "the two treatments agree,"
- Proving it.
As is often the case when proving things about programming languages, the tricky part here is formulating a precise statement to be proved - the proof itself should be straightforward.
Observation:
badnatcontainswrongand normal booleans.badboolcontainswrongandnv.- So, a term can fall within multiple syntactic categories.
Solution
- Call the original operational semantics .
Call the original operational semantics .
For conciseness, we skip the proofs for the determinacy of the single-step evaluation for and .
We treat each operational semantic as a partial function from terms to terms such that:
- If there exists a normal form term such that then .
- Otherwise, .
Then, is equivalent to iff:
- .
- For each term that is syntactically valid in , if is a value, then .
- For each term that is valid in , stucks .
- It's pretty trivial that evaluations in and always terminate.
Because is a superset of and both are deterministic, if yields a value, must also yield a value.
If stucks then such that is a normal form but not a value.
Then, because is a superset of and both are deterministic, .
We consider the possible forms of a stuck term in .
- .
Then, must be .
Then, .
- .
Then, itself must be stuck in .
Then, by the induction hypothesis, .
Then, applying rule E-Pred, we have .
- .
Similar to the above case.
- .
Similar to the above case.
Exercise 3.5.17
Statement. Two styles of operational semantics are in common use.
The one used in this book is called the small-step style, because the definition of the evaluation relation shows how individual steps of computation are used to rewrite a term, bit by bit, until it eventually becomes a value.
On top of this, we define a multi-step evaluation relation that allows us to talk about terms evaluating (in many steps) to values.
An alternative style, called big-step semantics (or sometimes natural semantics), directly formulates the notion of "this term evaluates to that final value," written . The big-step evaluation rules for our language of boolean and arithmetic expressions look like this:
Show that the small-step and big-step semantics for this language coincide, i.e. iff .
Observation: The right-hand-side for the is always a normal form.
Proof
TODO
Exercise 3.5.18
Statement. Suppose we want to change the evaluation strategy of our language so that the and branches of an expression are evaluated (in that order) before the guard is evaluated. Show how the evaluation rules need to change to achieve this effect.
Solution
- Remove
E-If. - Add rule
E-IfThen:
- Add rule
E-IfElse:
- Add rule
E-IfCond:
Related resources
Abstract and concrete syntax, parsing: Dozens of textbooks on compilers.
Inductive definitions, systems of inference rules, and proofs by induction: [Winskel, 1993; Hennessy, 1990].
The style of operational semantics that we are using here: A technical report by [Plotkin, 1981].
The big-step style (Exercise 3.5.17): [Kahn, 1987].
See [Astesiano, 1991] and [Hennessy, 1990] for more detailed developments.
Structural induction was introduced to computer science by [Burstall, 1969].