CS 641 Lecture -*- Outline -*- * Reasoning with program variables (5.3) ------------------------------------------ REASONING WITH PROGRAM VARIABLES (5.3) Def P_a.x means assumption (a) holds for x P_b.x.y means assump (b) for x & y etc. Def: var x1: T1, ..., xn:Tn means the set of assumptions that contains, for all 1 <= i <= n, 1 <= j <= n, i != j: P_a.xi, P_c.xi, P_e.xi, xi == val.xi P_b.xi.xj, and P_d.xi.xj. Example: var x:Int, y: Bool means the set of assumptions: val.x.(set.x.a.s) == a set.x.a; set.x.b == set.x.b set.x.(val.x.s).s == s x == val.x val.y.(set.y.a.s) == a set.y.a; set.y.b == set.y.b set.y.(val.y.s).s == s y == val.y val.x.(set.y.a.s) == val.x.s set.x.a; set.y.b == set.y.b; set.x.a val.y.(set.x.a.s) == val.y.s set.y.a; set.x.b == set.x.b; set.y.a ------------------------------------------ ------------------------------------------ GROWING AND SHRINKING ENVIRONMENTS/ASSUMPTIONS Monotonicity: Phi |- t ___________ Phi,t' |- t So for variables: var x1, ..., xm |- t _________________________________ var x1, ..., xm, y1, ..., yn |- t Change of variables var x1, ..., xm |- t _________________________________ var y1, ..., ym |- t[x1,...,xm := y1,...,ym] * if y1,...,ym are distinct, and if y1,...,ym are free for x1,...,xm in t ------------------------------------------ ** substitution property an important lemma ------------------------------------------ SUBSTITUTION PROPERTY Lemma 5.1 (substitution lemma). Suppose x:S and y:T are state attributes. Suppose that e and f are expressions such that {x:S,y:T} |- e:S and {x:S,y:T} |- f:S. Then for all states s, var x:S, y:T |- e.((x := f).s) == e[x := f].s ------------------------------------------ Q: How to prove this? Use inducation on the structure of the expression e. Q: Does this generalize to multiple assignments? yes ------------------------------------------ Corollary 5.2. Let x:S and y:T be state attributes. Suppose {y:T} |- e:S and {x:S,y:T} |- f:S. Then for all states s, var x:T |- e.((x := f).s) == e.s ------------------------------------------ Q: How does this follow from the substitution lemma? ** Assignments as state transformers ------------------------------------------ Composing Successive Assignments Theorem 5.3. Suppose x:T, {x:T} |- f:T, and {x:T} |- e:T. Then var x:T |- (x := e); (x := f) == (x := f[x := e]) Proof: Let s be a state. ((x := e); (x := f)).s ------------------------------------------ This works for assignments that assign the same variables. Q: How can we use this theorem for assignments to different variables? Pad them out: Lemma 5.4. Suppose that x:S and y:T are disjoint lists of attributes. Then var x:S, y:T |- (x := e) == (y,x := y,e). Work the proof of this. Example: (x, y := e, f); (y,z := g, h) Q: What does this say about assignments to distinct variables? That you can do substitutions on the expressions to convert to multiple assignments. And that you can reorder if the expressions are also independent. See corollary 5.5 ** straight-line programs (5.4) ------------------------------------------ STRAIGHT-LINE PROGRAMS (5.4) Grammar: f ::= id | x := e | f1 ; f2 where e is an expression Example: x := x + y; y := x - y; x := x - y ------------------------------------------ What's the state space for this example? *** typing ------------------------------------------ TYPING What's the state space of x := x - y ? a. {x:Int, y: Int} b. {x:Int, y: Int, z: Int} c. {x:Int, y: Int, z: Bool, w: Bool} Def: TE1 and TE2 are similar for program P iff P is well-typed in both TE1 and TE2. Def: if P is well-typed in both TE1 and TE2, then P: TE1 is similar to P: TE2. Alternative: think of progam as polymorphic P : TE -> TE for all type environments TE ------------------------------------------ Q: So what does similar really mean for state transformers? they are syntactically the same when expressed as straight-line programs *** example ------------------------------------------ var x: Nat, y:Nat |- (x := x+y); (y := x-y); (x := x-y) ------------------------------------------ ... boil this down to x,y := y,x ** Procedures (5.5) ------------------------------------------ PROCEDURES WITH CALL-BY-REFERENCE (5.5) ^ swap.x.y = (x := x+y); (y := x-y); (x := x-y) So var a, b |- swap.a.b == (a,b := b,a) ------------------------------------------ Q: Why does this hold? ------------------------------------------ ALIASING What is swap.a.a? Violates indepence assumptions var a,a So var a, b |- swap.a.b == (a,b := b,a) does not mean that var a, a |- swap.a.a == (a,a := a,a) instead var a |- swap.a == (a := 0) But (a,a := a,a) == skip Nonaliasing requirement for call by reference: Procedures must be applied to distinct actuals. ------------------------------------------ ** blocks and value parameters (5.6) ------------------------------------------ BLOCKS (5.6) Def: Let TE1 and TE2 be such that for all x:S \in TE1, x:S \in TE2. Then state transformers begin: TE1 -> TE2 and end: TE2 -> TE1 are a state extension pair between TE1 and TE2 iff they satisfy begin; end == id (g) Idea: begin maps s to a copy of s inside the larger state space If f: TE2 -> TE2, then we call begin; f; end a *block*. ------------------------------------------ this is similar to will be done to add new abstract data types to the language. Draw commuting diagram for the block *** local variables ------------------------------------------ PROPERTIES OF STATE EXTENSION PAIRS Let TE1 and TE2 be such that for all xi:Ti \in TE1, xi:Ti \in TE2. Let begin, end be a state extension pair between TE1 and TE2. Named independence assumptions for all xi:Ti \in TE1, yj:Sj \in TE2 s.t. yj:Sj \not\in TE1, TE1 |- ai: Ti, TE2 |- bj: Si (xi := ai); begin == begin; (xi := ai) (h) (xi := ai); end == end; (xi := ai) (j) val.xi == end; val.xi (k) (yj := bj); end == end (l) Shorthand: begin var y1,...,yn := e1, ..., en; f end =^= begin; (y1,...,yn := e1 o end,...,en o end); f; end where the ei do not use y1, ..., yn ------------------------------------------ Condition (l) says the yj variables in TE2 are local to the block Q: What do conditions (h)-(k) mean? draw commuting diagrams Q: What does e1 o end mean? (e1 o end).s = e1.(end.s) so we take out all of the new stuff in s before evaluating e1, i.e., we evaluate e1 in the global state Q: How could you implement begin and end to have these properties? Use pairing for begin, and projection for end Q: Should we permit redeclaration and shadowing? the authors do Q: Can we omit the initializers? Sure, if there is a convention to desugar initializers to some default value. *** working with blocks ------------------------------------------ PROVING PROPERTIES OF BLOCKS Example: var x, y |- begin var z := x; x := y; y := z end ------------------------------------------ ... == { definition of block syntax } begin; z := x o end; "x := y; y := z"; end == { assignment reasoning (exercise 5.6) } begin; z := x o end; "x,y := y,x; end" == { block property (j) } begin; "z := x o end; end"; x,y := y,x == { block property l, z is local } begin; end; x,y := y,x == { block property (g)} x,y := y,x Generalization of the above... ------------------------------------------ BLOCK/LOCAL INTRODUCTION RULES ______________________(block introduction) Phi |- f == begin var y := e; f' end * if f and f' are similar, and if f is written using only assignments __________________(local var introduction) Phi |- begin var z := e'; f end == begin var y,z := e,e'; f' end * if f and f' are similar. ------------------------------------------ Q: What does similar mean again? Q: So why do we have both f and f' here? *** value parameters Can use blocks to do other procedure mechanisms ------------------------------------------ CALL BY VALUE PARAMETERS Mode notation (a la Pascal): var mode = by reference val mode = by value Notation: proc set_it(var x, val e) = (x := e) means ^ set_it.x.e = (x := e) Call by value handled at call site: ^ set_it(y,3) = begin var e' := 3; set_it.y.e' end ------------------------------------------ Q: How does that model call by value? Q: Can this handle recursion? no, couldn't get it to stop with straight-line programs *** local procedure definitions ------------------------------------------ LOCAL PROCEDURE DEFINTIONS proc f(var x, val y) = s in ... f(u,e)... =^= let f = (\ x y . s) in ... begin var y' := e; f.u.y' end ... ------------------------------------------ Q: Do we have to be careful choosing the name y' in general? Yes, avoid name clashes so don't get inadvertent shadowing