CS221/321 Lecture 7, Oct 26, 2010 Where do we go from here? ------------------------- Various possible directions: (1) (functional) control flow continuations exceptions coroutines (pseudo)concurrent threads (2) state reference cells with assignment imperative commands (vs expressions) monadic state (3) types static typing judgements and inference rules type soundness We are going to first look at types. ---------------------------------------------------------------------- Section 4: Types ---------------- Lets first do a simpler exercise involving SEAL. Here we have only one type of value being expressed: natural numbers. So there is no possibility of conventional type errors. But there is a way that syntactically correct expressions can fail to be evaluated: the presence of free variables. So a "bad" expression is one that has free variables: Bad = {e ∈ expr | FV(e) ≠ ∅} We want to create a system of rules that will exclude bad expressions, thereby defining the set of good expressions whose evaluation can be completed. These are the expressions that have a "meaning". This property of being good cannot be captured by a simple inductive definition on SAEL expressions, because, for instance: let x = 3 in x is good, it has no free variables, but it contains a bad subexpression, the body x. So we need to define a more liberal property of being good with respect to a given set of variables (that are assumed to be properly bound in some outer context). Defn: Judgement: Let Γ be a set of variables. The judgement Γ ⊦ e ok says that e is good with respect to Γ, i.e. FV(e) ⊆ Γ. We can also say that e is "closed relative to Γ" or e is "closed in Γ". The "truly good" expression are those for which we can prove ∅ ⊦ e ok. ---------------------------------------------------------------------- Figure 4.1: Rules for relative closure: Γ ⊦ e ok ---------------------------------------------------------------------- Rules: (1) ---------------- Γ ⊦ Num(n) ok (2) (x ∈ Γ) ----------- Γ ⊦ x ok (3) Γ ⊦ e1 ok Γ ⊦ e2 ok ---------------------------- Γ ⊦ Bapp(bop,e1,e2) ok (4) Γ ⊦ e1 ok Γ ⋃ {x} ⊦ e2 ok ---------------------------------- Γ ⊦ let x = e1 in e2 ok ---------------------------------------------------------------------- So asserting that "Γ ⊦ e ok" is really asserting that there is a derivation of that judgement using these rules. Of course, for this property, it is not clear that we have gained much expressing it through an inference system as opposed to using the computed property of the expression given by FV(e) = ∅. But when we go to full type systems, using inference rules be more clearly useful. [But keep asking why.] So now we want to show that for good expressions, small-step evaluation will successfully terminate in a value. (Nothing will "go wrong".) Theorem 4.1: ∅ ⊦ e ok => ∃n. e ↦! Num(n). Intuition: If e is closed (no free variables), we will never find outselves trying to evaluate a variable. We can be sure of this if we can show that: (1) At each point in the transition sequence, the current expression is closed, i.e. the property of being closed is preserved by all transitions. (2) If e is closed, either e is a value, and we are finished with evaluation, or, if not, then there is a transition defined for e (by the SEAL[SSv] rules). We call the first property "preservation" (of closure), and the second property is called "progress" (we can always make progress if we have a closed, nonvalue expression). We formalize these two propositions as the Preservation and Progress Lemmas. Lemma [Preservation]: ∅ ⊦ e ok & e ↦ e' => ∅ ⊦ e' ok. Lemma [Progress]: ∅ ⊦ e ok => e a value or ∃e'. e ↦ e'. ------------------- We will prove the Preservation lemma by induction on the derivation of the premise e ↦ e', using the rules in Fir. 2.4 for SAEL[SSv]. For the Rule (5) base case, we will need two technical lemmas: Inversion for the ok rules (Fig 4.1 above), and a Substitution lemma. Lemma 4.2 [Inversion]: (1) Γ ⊦ x ok => x ∈ Γ (2) Γ ⊦ Bapp(bop,e1,e2) ok => Γ ⊦ e1 ok & Γ ⊦ e2 ok (3) Γ ⊦ let x = e1 in e2 ok => Γ ⊦ e1 ok & Γ⋃{x} ⊦ e2 ok Proof: The proof consists simply of observing that a derivation of an ok judgement entails derivations of its premises. (1) A derivation of Γ ⊦ x ok must be by rule ok(2), because that is the only rule that applies for a variable exression like x. Hence in that derivation, the premise of ok(2) must hold, i.e. x ∈ Γ. [X] (2) A derivation of Γ ⊦ Bapp(bop,e1,e2) ok must have ok(3) as its final rule, because only that rule matchines the expression Bapp(bop,e1,e2). Hence the premises of that rule, namely Γ ⊦ e1 ok & Γ ⊦ e2 ok must be the conclusions of the subderivations. [X] (3) Similar. [X] Lemma 4.3 [Weakening]: Γ ⊦ e ok & Γ ⊆ Γ' => Γ' ⊦ e ok. Proof. Induction on the derivation of Γ ⊦ e. [Exercise] We prove the following Substitution lemma in a general form, where we are substition an arbitrary expression rather than a value expression, since the general form can be used for a by-name version of the Preservation Lemma as well. The Substitution Lemma says that if e1 has free variables in Γ, and e2 has free variables in Γ⋃{x}, then substituting e1 for x in e2 yields an expression having free variables in Γ (the additional free variable x having been eliminated by the substitution). Lemma 4.4 [Substitution]: Γ ⊦ e1 ok & Γ⋃{x} ⊦ e2 ok & x ∉ Γ => Γ ⊦ [e1/x]e2 ok. Proof: By induction on the derivation d of Γ⋃{x} ⊦ e2 ok, using the rules of Fig. 4.1. From any such derivation d we can derive two values: the context Γ and the subject expression e of the derivations final conclusion, Γ ⊦ e ok. We will call these context(d) and subject(d). Comments: We might proceed naively, doing the case analysis on the (final) rule used for deriving the Γ⋃{x} ⊦ e2 ok judgement. Lets consider the case for Rule[ok] (4) (from Fig 4.1 above). Case: Γ⋃{x} ⊦ e2 ok by Rule (4). Then e2 is of the form "let y = e3 in e4" for some y, e3, and e4. Lets assume what seems like the natural induction hypotheses: IH1: Γ ⊦ [e1/x]e3 ok IH2: Γ⋃{y} ⊦ [e1/x]e4 ok Then by Rule (4) and these two induction hypotheses, we have Γ ⊦ let y = [e1/x]e3 in [e1/x]e4 ok and then by the definition of substitution and the assumption that the variable y is different from x, we get the desired case conclusion: Γ ⊦ [e1/x](let y = e3 in e4) ok But note that the contexts for IH1 and IH2 differ, and the context for IH2 also differs from Γ in the conclusion. What exactly is the statement that is being proved here, and how does it accomodate this variation in the context in the IHs? What we actually need to prove is a slightly stronger statement than the statement of the Lemma itself. It is roughly (1) ∀e1.∀Γ. Γ ⊦ e1 ok => (∀e2.∀Γ'.∀x∈Var. x∉Γ & Γ⊆Γ' & Γ'⋃{x} ⊦ e2 ok => Γ ⊦ [e1/x]e2 ok) The quantification over the superset Γ' of Γ provides the flexibility needed for the IH for the Let body (IH2 above). But since we are proving this be induction on _derivations_ of the ok judgement, we really need to restate (1) in terms of derivations d in D[ok], the inductively defined set of ok derivations. (1') ∀e1.∀Γ. Γ ⊦ e1 ok => (∀d∈D[ok].∀x∈Var. x∉Γ & Γ⊆context(d) & context(d) ⊦ subject(d) ok => context(d)\{x} ⊦ [e1/x]subject(d) ok) where subject(d) is the expression part of the conclusion judgement of d, i.e. e2, and context(d) is the context part of that judgment, i.e. Γ'. Of course, the conjunct (context(d) ⊦ subject(d) ok) is true by definition, so it is redundant, and (1') can be simplified to: (1'') ∀e1.∀Γ. Γ ⊦ e1 ok => (∀d∈D[ok].∀x∈Var. x∉Γ & Γ⊆context(d) => context(d)\{x} ⊦ [e1/x]subject(d) ok) We will assume given a Γ and e1 such that Γ ⊦ e1 ok, and a variable x ∉ Γ. Then we want to prove that ∀d∈D[ok].P(d), where P is the property given by: (2) P(d) == Γ ⊆ context(d) => context(d)\{x} ⊦ [e1/x]subject(d) ok Now let us be precise about the structure of derivations and the definitions of context and subject of a derivation. Derivations d in D[ok] are inductively constructed using rule-constructors corresponding to the four rules of Fig 4.1: d ::= Rule1(Γ, n) | Rule2(Γ, x) | Rule3(bop,d1,d2) -- d1 and d2 are the derivations for e1 and e2 | Rule4(x,d1,d2) We define the subject and context functions for derivations as follows: subject(Rule1(Γ, n)) = Num n subject(Rule2(Γ, x)) = Var x subject(Rule3(bop,d1,d2)) = Bapp(bop,subject(d1),subject(d2)) subject(Rule4(x,d1,d2)) = Let(x,subject(d1),subject(d2)) context(Rule1(Γ, n)) = Γ context(Rule2(Γ, x)) = Γ context(Rule3(bop,d1,d2)) = context(d1) context(Rule4(x,d1,d2)) = context(d1) These rule constructors are not "free" constructors, because a valid construction of a derivation has to satisfy some side constrains, specified as follows: Rule2(Γ,x) : x ∈ Γ Rule3(bop,d1,d2) : context(d1) = context(d2) Rule4(x,d1,d2) : context(d2) = context(d1) ⋃ {x} Now we prove ∀d.P(d), where P is as defined in (2) above, for given context Γ, expression e1, and variable x. Base Case: d = Rule1(Γ',n). Then let e2 = subject(d) = Num(n), and note that context(d) = Γ'. Then [e1/x]e2 = Num(n) by the definition of substitution. By ok(1), Γ'' ⊦ Num(n) ok for any context Γ'', and in particular for Γ'\{x}. [X] Base Case: d = Rule2(Γ',y). Then let e2 = subject(d) = Var(y), and note that context(d) = Γ'. We can assume that Γ ⊆ Γ', since otherwise the premise of the implication P(d) is false and P(d) holds vacuously. There are two subcases. (a) y = x: In this case, [e1/x]e2 = e1. We know that Γ ⊦ e1 ok, and hence Γ'\{x} ⊦ e1 ok, by Lemma 4.3, since Γ ⊆ Γ'\{x} because of the assumption that x ∉ Γ. (b) y ≠ x: In this case, [e1/x]e2 = e2 = Var(y). It must be the case that y ∈ Γ' by the Rule2 constraint, and since y ≠ x, y ∈ Γ'\{x}. Hence Γ'\{x} ⊦ Var(y) ok by ok(2). So Γ'\{x} ⊦ [e1/x]e2 ok. [X] Ind Case: d = Rule3(bop,d1,d2). Let e3 = subject(d1) and e4 = subject(d2) and Γ' = contect(d) = context(d1) = context(d2), by the Rule3 constraint and the defn of context. So e2 = subject(d) = Bapp(bop,e3,e4). If Γ ⊄ Γ', then P(d) holds vacuously, so we can assume Γ ⊆ Γ'. IH1: P(d1) == Γ ⊆ Γ' => Γ'\{x} ⊦ [e1/x]e3 ok IH2: P(d2) == Γ ⊆ Γ' => Γ'\{x} ⊦ [e1/x]e4 ok By IH1 and the assumption that Γ ⊆ Γ', we have Γ'\{x} ⊦ [e1\x]e3 ok. Similarly, by IH2 we have Γ'\{x} ⊦ [e1\x]e4 ok. Then by rule ok(3) we have Γ'\{x} ⊦ [e1\x]Bapp(bop,e3,e4) ok, and hence Γ'\{x} ⊦ [e1\x]e2 ok by the defn of substitution. [X] Ind Case: d = Rule4(y,d1,d2). Let e3 = subject(d1) and e4 = subject(d2) and Γ' = contect(d1). Then it must be the case that Γ'' = context(d2) = Γ'⋃{y} by the Rule4 constraint. We then have e2 = Let(y, e3, e4). We can assume that the local let-bound variable y is chosen so that y ≠ x and y ∉ FV(e3) (by α-converting, if necessary, to make it so). We can also assume that Γ ⊆ Γ', since otherwise P(d) is true vacuously. Since Γ' ⊆ Γ'', we also have Γ ⊆ Γ''. IH1: P(d1) == Γ ⊆ Γ' => Γ'\{x} ⊦ [e1/x]e3 ok IH2: P(d2) == Γ ⊆ Γ'' => Γ''\{x} ⊦ [e1/x]e4 ok By IH1 and the fact that Γ ⊆ Γ', we have Γ'\{x} ⊦ [e1/x]e3 ok (1) and by IH2 and Γ ⊆ Γ'' we have Γ''\{x} ⊦ [e1/x]e4 ok (2) Since Γ''\{x} = (Γ'\{x})⋃{y}, we can conclude from (1), (2) and rule ok(4) that Γ'\{x} ⊦ Let(y,[e1/x]e3,[e1/x]e4) ok (3) But by the definition of substitution and the assumption that y ≠ x and y ∉ FV(e1), Let(y,[e1/x]e3,[e1/x]e4) = [e1/x](Let(y,e3,e4)) = [e1/x]e2. (4) Hence by (3) and (4), we have Γ'\{x} ⊦ [e1/x]e2 ok. [XX] Lemma 4.5 [Preservation]: ∅ ⊦ e ok & e ↦ e' => ∅ ⊦ e' ok. Proof: By induction on the derivation d of e ↦ e'. We will use the Rule constructs for SEAL[SSv] (Figure 2.4, Lect 4) given in the solution of Homework 1 (sol1.txt), modified to use the general Bapp constructor instead of Plus, Times. We must prove ∀d. P(d), where P(d) = ∅ ⊦ source(d) ok => ∅ ⊦ target(d) ok Base Case: d = Rule1(bop,n1,n2). Then e = Bapp(bop,Num(n1),Num(n2)) and e' = Num(p) where p = prim(bop,n1,n2). We have ∅ ⊦ e' ok by ok(1) [Rule (1) for the ok judgement]. Ind Case: d = Rule2(bop,e2,d'). Then e = Bapp(bop,e1,e2) and e' = Bapp(bop,e1',e2) where e1 = source(d') and e1' = target(d'). IH: P(d'), or ∅ ⊦ e1 ok => ∅ ⊦ e1' ok. Assume: ∅ ⊦ Bapp(bop,e1,e2) ok => [Inversion of ok(3)] ∅ ⊦ e1 ok (1) & ∅ ⊦ e2 ok (2) => [(1), IH] ∅ ⊦ e1' ok (3) => [(2), (3), ok(3)] ∅ ⊦ Bapp(bop,e1',e2) ok. => [Defn e'] ∅ ⊦ e' ok. [X] Ind Case: d = Rule3(n1,d'). Similar to Rule2 case. Ind Case: d = Rule4(x,e2,d'). Then e = Let(x,e1,e2) and e' = Let(x,e1',e2) where e1 = source(d') and e1' = target(d'). IH: P(d'), or ∅ ⊦ e1 ok => ∅ ⊦ e1' ok. Assume: ∅ ⊦ Let(x,e1,e2) ok => [Inversion(4)] ∅ ⊦ e1 ok (1) & {x} ⊦ e2 ok (2) => [(1), IH] ∅ ⊦ e1' ok (3) => [(3),(2), ok(4)] ∅ ⊦ Let(x,e1',e2) ok => ∅ ⊦ e' ok [X] Base Case: d = Rule5(x,n,e2). Then e = source(d) = Let(x, Num(n), e2) and e' = target(d) = [Num(n)/x]e2. Assume: ∅ ⊦ Let(x,Num(n),e2) ok => [Inversion(4)] ∅ ⊦ Num(n) ok (1) & {x} ⊦ e2 ok (2) => [Substitution] ∅ ⊦ [Num(n)/x]e2 ok. => ∅ ⊦ e' ok. [X] Lemma 4.6 [Progress]: ∅ ⊦ e ok => e a value or & ∃e'. e ↦ e'. Proof: By induction on the derivation of ∅ ⊦ e ok. Base Case: d = Rule1(n). e = Num(n). e is a value. [X] Base Case: d = Rule2(x). e = Var(x). Impossible. Ind Case: d = Rule3(bop,d1,d2). e = Bapp(bop, e1, e2) where e1 = subject(d1) and e1 = subject(d2). IH1. e1 closed => e1 a value or e1 -> e1' IH2. e2 closed => e2 a value or e2 -> e2' Inversion: e1 closed and e2 closed. => e1 a value or e1 -> e1' e2 a value or e2 -> e2' The following Theorem is often paraphrased as "evaluation of a closed expression will not get stuck". Theorem 4.7. If ∅ ⊦ e ok, then either evaluation of e diverges, or ∃n. e ↦! Num(n). Proof. Suppose e ↦* e'. We can prove that ∅ ⊦ e' ok using the Preservation Lemma (Lemma 4.5) and induction on the definition of ↦*. Thus each step of evaluation Lemma 4.6 applies, and we are either finished, if e' = Num(n), or we can continue with another transition, e' ↦ e''.