CS221/321 Lecture 2, 9/30/2010 ------------------------------- [Note on terminology: we use the words "expression" and "term" interchangeably.] How do we precisely define how arithmetic expressions are evaluated? 1. By writing a program implementing evaluation (say in ML). ------------------------------------------------------------ Program 1.1: SAE eval (SAE-interp.sml) ------------------------------------------------------------ datatype expr = Num of int | Plus of expr * expr | Times of expr * expr (* eval : expr -> int *) fun eval (Num n) = n | eval (Plus(e1,e2)) = eval e1 + eval e2 | eval (Times(e1,e2)) = eval e1 * eval e2 val exp1 = Plus(Num 2, Times(Num 13, Num 4)) eval exp1 ==> 54 ------------------------------------------------------------ 2. But what if we want to define evaluation "mathematically"? Define an abstract grammar of simple arithmetic expressions (SAEs) n :: = (i.e. n ∈ Nat) expr :: = Num n | Plus(expr,expr) | Times(expr,expr) We define a binary evaluation relation: ---------------------------------------------------------------------- Figure 1.1: SAE[BS] - Eval relation ---------------------------------------------------------------------- Eval ⊆ expr × Nat Eval ((Num n),n) Eval ((Plus(e1,e2)), p) <= Eval (e1, n1) & Eval (e2, n2) & p = n1 + n2 Eval ((Plus(e1,e2)), p) <= Eval (e1, n1) & Eval (e2, n2) & p = n1 + n2 ---------------------------------------------------------------------- Alternatively, we can use an infix down arrow symbol (⇓) to represent the Eval relation: ---------------------------------------------------------------------- Figure 1.1a: SAE[BS] - ⇓ evaluation relation ---------------------------------------------------------------------- ⇓ ⊆ expr × nat Rules: (1) (Num n) ⇓ n (2) Plus(e1,e2) ⇓ p <= e1 ⇓ n1 & e2 ⇓ n2 & p = n1 + n2 (3) Times(e1,e2) ⇓ p <= e1 ⇓ n1 & e2 ⇓ n2 & p = n1 * n2 ---------------------------------------------------------------------- Is evaluation deterministic? I.e. For any e, is the n such that e ⇓ n unique? Intuitively, we certainly expect so. Theorem 1.1: ∀e ∀m ∀n. e ⇓ m & e ⇓ n => m = n Exercise: How do we prove it? ----------------------- This Eval (⇓) relation defines what is known as a "big-step" semantics, because it relates an expression to its final value, ignoring how many intermediate steps of computation are involved in the evaluation. ====================================================================== Note: On the inductive definition of expr The BNF definition expr :: = Num n | Plus(expr,expr) | Times(expr,expr) defines the set of SAE expressions recursively, or "inductively". What is the meaning of such a definition? We are working in basic set theory, augmented with a notion of general expressions consisting of syntax constructors like Plus and Times applied to tuples of expressions. These expressions could be themselves encoded by basic set constructions, but we will just assume them as primitives. It is assumed that syntax constructors are 1-1 functions, so, for instance, Plus(e1,e2) = Plus(e1',e2') implies e1 = e1' and e2 = e2'. Num is assumed to be a 1-1 function mapping Nat to expressions. Furthermore the ranges of Nat, Plus, and Times are disjoint; expressions formed by Nat, Plus, and Times are always distinct. We define a "set closure" function C as follows: C(S) = {Num(n) | n ∈ Nat}⋃ {Plus(s1,s2) | s1, s2 ∈ S} ⋃ {Times(s1,s2) | s1, s2 ∈ S} Such a closure function maps sets to sets and is monotonic: A ⊆ B => C(A) ⊆ C(B). Define a sequence of sets E(i) as follows: E(0) = ∅ E(n+1) = C(E(n)) For instance, E(1) = {Num(n) | n ∈ Nat} E(2) = {Num(n) | n ∈ Nat} ⋃ {Plus(Num(n1),Num(n2)) | n1, n2 ∈ Nat} ⋃ {Times(Num(n1),Num(n2)) | n1, n2 ∈ Nat} and in general E(n) is the set of terms built from Num, Plus and Times of depth less than or equal to n. Note that E(n) ⊆ E(n+1), and each finite expression e in SAE will appear in E(n), where n = depth(e), defined by: depth(Num(n)) = 1 depth(Plus(e1,e2)) = 1 + max(depth(e1), depth(e2)) depth(Times(e1,e2)) = 1 + max(depth(e1), depth(e2)) Now define the limit set E = ⋃{E(n) | n ∈ Nat} Prop: E is the least fixed point of C, i.e. (i) E = C(E). (ii) If S = C(S), then E ⊆ S. Proof: informal homework. We take E, the least fixed point of C to be the meaning of the inductive definition of expr, i.e. expr = E. Note that all the expressions in E are finite, because all the expressions in each E(n) are finite. This definition excludes "infinite expressions" such as the expression defined by the recursive equation e = Plus(e,e) which looks like an infinite binary tree with each node labeled by the Plus constructor. e = Plus / \ Plus Plus / \ / \ ... ... ... ... As a consequence, the relation of subexpression is a well-founded partial order on expr. This is the basis for structural induction on expressions. ======================================================================== Small-step semantics -------------------- A more fine-grained definition of evaluation takes into account all the intermediate steps involved. We define a "transition relation" on expressions (which is a binary relation on expressions): e ↦ e' ( ↦ ⊆ expr × expr ) where expression e' is obtained from expression e by one basic step of evaluation (i.e. by a single "reduction" of a redex subexpression). [For definitions and notation for transition systems, see Chapter 2, "Transistion Systems" in the Harper book. The expressions here are also known as "states" in a transition system. In this case, the initial states I = expr (i.e. all expressions are initial states), and the final states F = {Num(n) | n ∈ Nat}, i.e. the atomic expressions representing numbers.] We have to account for the fact that the place that the reduction takes place will generally be a subterm (possibly deeply nested) of the main expression we are evaluating. Here are some rules defining the small-step transition relation for evaluating SAEs. ---------------------------------------------------------------------- Figure 1.2: SAE[SS] ---------------------------------------------------------------------- (1) Plus(Num n1, Num n2) ↦ Num p where p = n1 + n2 (2) Plus(e1, e2) ↦ Plus(e1', e2) <= e1 ↦ e1' (3) Plus(Num n1, e2) ↦ Plus(Num n1, e2') <= e2 ↦ e2' (4) Times(Num n1, Num n2) ↦ Num p where p = n1 * n2 (5) Times(e1, e2) ↦ Times(e1', e2) <= e1 ↦ e1' (6) Times(Num n1, e2) ↦ Times(Num n1, e2') <= e2 ↦ e2' ---------------------------------------------------------------------- Rules (1) and (4) are called "instructions" or axioms. They specify the basic reductions. A term matching one of the patterns on the left is called a redex, and the reduced term on the right is called the "contractum". Rules (2), (3), (5), and (6) are called "search rules". They are used to isolate the site of a redex and propagate the reduction of the redex to the larger enclosing expression. See lecture2.pdf for the conventional presentation this set of "inference" rules, with a line separating premisses above the line and a conclusion below the line. How do we use these rules to justify a reduction like: 2 + (13 * 4) ↦ 2 + 52 ? We have to "prove" this transition using a derivation from the rules. (To make terms and derivations more concise, we'll leave out the Num constructors and just treat the numbers themselves as basic expressions.) ---------------------------------------------------------------------- Figure 1.3: Example: 2 step derivation ---------------------------------------------------------------------- ------------------ (2) Times(13,4) ↦ 52 ------------------------------------ (5) Plus(2, Times(13,4)) ↦ Plus(2, 52) ---------------------------------------------------------------------- This is called a proof tree or a derivation tree. Each node is labeled by the rule that justifies the inference. A search rule like (5) promotes a transition on a subexpression to a transition on the (immediate) containing expression. If the redex is nested more deeply, the transition derivation will also be deeper. In fact, its shape exactly corresponds to the form of the expression in the conclusion. The transition 2 + ((5 + 8) * 4) ↦ 2 + (13 * 4) ----- has the derivation ---------------------------------------------------------------------- Figure 1.4: Example: 3 step derivation ---------------------------------------------------------------------- ---------------- (1) Plus(5,8) ↦ 13 ----------------------------------- (4) Times(Plus(5,8),4)) ↦ Times(13,4) --------------------------------------------------- (5) Plus(2,Times(Plus(5,8),4)) ↦ Plus(2,Times(13,4)) ---------------------------------------------------------------------- Observe that the left-hand-sides of the transitions in this derivation are just the nested sequence of subexpressions along the path from the root of the full term to the redex subexpression. This will be true in general, so the structure of any reduction derivation reflects the path from the root to the redex subexpression of the expression being reduced. How do we get full evaluation from the transition relation ↦ ? We construct sequences of chained transitions: e1 ↦ e2 ↦ e3 ↦ ... ↦ e How do we know we are done? When there are no further transitions possible. I.e when there does not exist an e' such that e ↦ e'. Such an expression/state is known as a final state. In this case, the final states are exactly the simple Num terms -- they are already fully evaluated. The set of final states is F = {Num(n) | n ∈ Nat} There are a number of natural questions to ask about this transition system. Question 1. Does evaluation always terminate? That is, for any given initial expression e1, is there always a complete transition sequence ending in a final state, that is, in a number expression? Question 2. Is evaluation deterministic? That is, does the evaluation of an expression, assuming it terminates, always yield the same, uniquely determined number? A question related to Question 2 is: Question 3. Is the transition relation deterministic, in the sense that for a given nonfinal expression (i.e. a compound expression) e1, there is a unique expression e2 such that e1 ↦ e2. An affirmative answer to Question 3 obviously implies an affirmative answer to Question 3. In fact, the answer for all three questions is yes. ====================================================================== Homework 1.2 ------------ Prove that small-step (transition) evaluation for SAE always terminates. Homework 1.3 ------------ Prove that the transistion relation is deterministic: for any e ∈ expr, there exists at most one e' such that e ↦ e'. ====================================================================== Comparing Big-Step and Small-Step evaluation Now we have two alternate explanations of evaluation of SAE, using either the big-step semantics ⇓ or the small-step semantics ↦. We would hope that they are consistent with one another, and this is indeed the case. Theorem 1.2. For all e ∈ expr and n ∈ Nat, e ⇓ n <=> e ↦! Num(n). ====================================================================== Homework 1.4 ------------ Prove Theorem 1.2. ======================================================================