Recall the definition of the syntax of our language: int ------------ var ----------- i in Exp x in Exp e1 in Exp e2 in Exp plus --------------------- e1 + e2 in Exp e1 in Exp e2 in Exp times --------------------- e1 * e2 in Exp We write |- e in Exp if we can construct a derivation (i.e., formal proof tree using the rules above) to conclude that e is an expression. The definition of our abstract machine states: s in Store : Var -> Int MS in MachineState ::= (e, s) Finally, recall the inference rules that allow us to conclude that (e,s) transitions to (e',s): t-var ------------------ (x, s) => (s(x),s) t-plus ------------------ (i = i1+i2) (i1+i2,s) => (i,s) t-times ------------------ (i = i1*i2) (i1*i2,s) => (i,s) (e1,s) => (e1',s) t-lplus ----------------------- (e1+e2,s) => (e1'+e2,s) (e2,s) => (e2',s) t-rplus ----------------------- (i1+e2,s) => (i1+e2',s) (e1,s) => (e1',s) t-ltimes ----------------------- (e1*e2,s) => (e1'*e2,s) (e2,s) => (e2',s) t-rtimes ----------------------- (i1*e2,s) => (i1*e2',s) We write |- (e1,s) => (e2,s) if we can construct a derivation that (e1,s) steps to (e2,s) using the transition rules above. ------------------------------------------------------ We define the height of a proof tree P as follows: If P is an instance of an axiom, then height(P) = 0. If P is a proof tree whose root ends with an instance of an inference rule, then the height of P is 1 + the maximum of the heights of the proofs that make up the sub-trees of the proof, corresponding to the assumptions. ------------------------------------------------------ Theorem: if |- e in Exp and s is a store, then either e is an integer and there is no e' such that (e,s) => (e',s), or else there exists a unique e' such that |- (e,s) => (e',s). We argue the proof by induction on the height h of the proof tree P that allows us to conclude that e in Exp. If the proof tree P has height 0, then the proof tree must end with an axiom (see the definition of height above). There are two axioms that allow us to conclude e in Exp, the int and var rules. For the int rule, the theorem is immediately satisfied since i is an integer, and by inspection of the conclusions of the rules, there is no transition that allows us to move to a new expression when starting from an integer. For the var rule, we must show there is a unique e' such that (x,s) => (e',s). By inspection of the transition rules, only the t-var rule can apply: t-var ------------------ (x,s) => (s(x), s) and this allows us to conclude that e' = s(x). Since s is a function, there is at most one integer i such that s(x) = i. This concludes the base case where our proof tree has height 0. Now our induction hypothesis is: IH: For all e1, such that the proof of e1 in Exp is less than or equal to h, e1 is either an integer, or else there exists a unique e1' such that (e1,s) => (e1',s). Note that we are using strong induction here, since we're assuming the property holds for all proof trees smaller than h+1, (not just those proof trees of height h.) We must show that for a proof of e in Exp of height h+1, the theorem holds. Since the proof has height greater than 0, it must end with something besides an axiom. Thus, the proof must either end with an instance of the plus rule or the times rule. First case: Our proof P that e in Exp looks like this: P1 P2 --------- --------- e1 in Exp e2 in Exp plus ------------------------ e1 + e2 in Exp That is, e = e1 + e2. Note that the height of P1 and the height of P2 must be less than or equal to h, since the height of P is h+1. Applying the induction hypothesis to the proof P1 that e1 in Exp, e1 is either an integer i1 or else there exists a unique e1' such that (e1,s) => (e1',s). Similarly, by the induction hypothesis, e2 is either an integer i2 or else there exists a unique e2' such that (e2,s) => (e2',s). If e1 and e2 are both integers, then only one transition rule applies, namely t-plus. (t-lplus cannot apply since, by induction, there isn't a transition for e1 if it's an integer. Similarly, t-rplus cannot apply since, by induction, there isn't a transition rule for e2 if it's an integer.) If e1 is an integer, but e2 is not, then only one rule applies, namely t-rplus. (Note that t-plus doesn't match since e2 is not an integer, and t-lplus doesn't match since e1 is an integer and by induction, there is no transition for e1.) Since there is at most e2' such that (e2,s) => (e2',s), we can conclude that (e1+e2,s) => (e1+e2',s) and this is the only possible transition. Finally, if e1 is not an integer then only one rule applies, namely t-lplus. (Note that t-plus and t-rplus don't match since e1 isn't an integer.) Since there is at most one e1' such that (e1,s) => (e1',s), we can conclude that (e1+e2,s) => (e1'+e2,s) and this is the only possible transition. Second case: Our proof P that e in Exp looks like this: P1 P2 --------- --------- e1 in Exp e2 in Exp plus ------------------------ e1 * e2 in Exp The analysis proceeds in exactly the same fashion as for plus. QED. -------------------------------------------------------------------- Our theorem shows that evaluation of expressions is deterministic. That is, the transition relation is a partial function taking machine states to machine states. The machine is finished computing when we've reduced the expression to an integer. That is, we consider machine states of the form (i,s) as terminal states. So, we might define: eval(e,s) = i if (e,s) =>* (i,s) where we interpret =>* as the reflexive, transitive closure of the transition relation. More formally, we might define: Z ------------- eval(i,s) = i (e,s) => (e',s) eval(e',s) = i S --------------------------------- eval(e,s) = i There is yet another way that we could define eval directly, without appealing to the one-step transition rules: EI --------------- (i,s) evalsto i EV ------------------ (x,s) evalsto s(x) (e1,s) evalsto i1 (e2,s) evalsto i2 E+ -------------------------------------- (i = i1+i2) (e1+e2,s) evalsto i (e1,s) evalsto i1 (e2,s) evalsto i2 E* -------------------------------------- (i = i1*i2) (e1*e2,s) evalsto i The evalsto relation is an example of a big-step semantics because the evaluation of a sub-expression happens in one big step. In contrast, the => relation is a small-step semantics, which only captures one step in the abstract machine. For example, we can prove (3*4)+2 evalsto 14 like this: EI--------------- EI--------------- (3,s) evalsto 3 (4,s) evalsto 4 E*----------------------------------(12=3*4) EI--------------- (3*4,s) evalsto 12 (2,s) evalsto 2 E+------------------------------------------------------------- (14 = 12+2) ((3*4)+2,s) evalsto 14 Big-step semantics are often easier to use in reasoning about the answers that a program might produce, because we don't have to get caught up in all of the intermediate machine states. But big-step semantics have their own problems. In particular, they're not very good for modelling programs that might run forever (e.g., an operating system or server.) ---------------------------------------------------------------- Homework: Hand in to Prof. Morrisett in class next Monday (Sep. 8). Type your homework or write very, very neatly. Question 1: ----------- Prove that if |- e in Exp and s is a store, there exists a unique i such that (e,s) evalsto i. Question 2: ----------- Define a transition relation ==> that forces evaluation to go right-to-left instead of left-to-right. Question 3: ----------- Consider adding the following alternative transition semantics for our language (NOTE: I've fixed the bug that was mentioned in class for these rules.) t-var ------------------ (x, s) *> (s(x),s) t-plus ------------------ (i = i1+i2) (i1+i2,s) *> (i,s) t-times ------------------ (i = i1*i2) (i1*i2,s) *> (i,s) (e1,s) *> (e1',s) t-lplus ----------------------- (e1+e2,s) *> (e1'+e2,s) (e2,s) *> (e2',s) t-rplus ----------------------- (e1+e2,s) *> (e1+e2',s) (e1,s) *> (e1',s) t-ltimes ----------------------- (e1*e2,s) *> (e1'*e2,s) (e2,s) *> (e2',s) t-rtimes ----------------------- (e1+e2,s) *> (e1*e2',s) The rules are exactly the same as for => except that the t-rplus and t-rtimes rules are slightly different. How would our proof that there is at most one machine state that we can step to break? Give a counter example and then show where in the proof we would be making a flawed assumption. (Just cut and paste the text of my proof, put it in quotes, and say something about why it is wrong.) Question 4: ----------- Prove that eval(e,s) = i iff (e,s) evalsto i.