Com S 641 meeting -*- Outline -*- * Expression parameters (Schmidt 3.1-3.3) ** syntax of expression parameters to procedures (3.1) ------------------------------------------ EXPRESSION PARAMETERS TO PROCEDURES (3.1) Syntax: D ::= proc C ::= call I(E) Examples: var v: newint; proc p(i:int exp) = (v:=i; v:=i) in v := 1; call P(@v+1) FOR YOU TO DO Give the type checking rules ------------------------------------------ ... I1(I2:tau exp) = C where tau as usual is in {int, bool} Q: What is the type attribute of I1 in the type rule? do this for lazy and eager evaluation ** semantics (3.2) ------------------------------------------ EAGER SEMANTICS (3.2) Meaning of type attributes [[ tau exp -> comm]] = Semantics of declarations: [[ Semantics of invocations: [[ Semantics of formal parameter references: [[ ------------------------------------------ ... [[tau]] -> [[comm]] = [[tau]] -> Store -> Store_ ... [[pi|-proc I1(I2:tau exp)=C:{I1:tau exp -> comm}dec]]e s = ({I1 = p}, s), where p v s' = [[pi \-U {I2:tau exp}|-C:comm]](e\-U{I2:v}) s' ... [[pi|-call I1(E):comm]]e s = p([[pi|-E:tau exp]]e s) s, where (I1 = p) \in e ... [[pi|-I2:tau exp]]e s = v, where (I2=v) \in e Q: Does this satisfy the correspondence principle? no, because need 2 semantics for identifiers one time they are bound to values, but can also have function abstracts How could we disambiguate? (a) change the syntax! (b) use tau instead of tau exp as type attribute inside the procedure, have to change typing rule... Q: What if the actual parameter loops? need each p to be strict in val argument, so require that by "legislating" that p _|_ s = _|_ (In Haskell, use seq to force strictness) ------------------------------------------ LAZY SEMANTICS Meaning of type attributes [[ tau exp -> comm]] = Semantics of declarations: [[ Semantics of invocations: [[ Semantics of formal parameter references: [[ ------------------------------------------ ... [[tau exp]] -> [[comm]] = (Store -> [[tau]]) -> Store -> Store_ ... [[pi|-proc I1(I2:tau exp)=C:{I1:tau exp -> comm}dec]]e s = ({I1 = p}, s), where p f s' = [[pi \-U {I2:tau exp}|-C:comm]](e\-U{I2:f}) s' ... [[pi|-call I1(E):comm]]e s = p f s, where (I1 = p) \in e and f s' = [[pi|-E:tau exp]]e s' ... [[pi|-I2:tau exp]]e s = f s, where (I2=f) \in e Q: How does this work? Q: What would be another way to define this? use a copy rule, see 3.3 ** type soundness Q: What's involved in trying to prove type soundness for the lazy semantics? What are the new type attributes? Their meaning? [[t1 -> t2]] = [[t1]] -> [[t2]] e.g. [[int exp -> comm]] = [[int exp]] -> [[comm]] = (Store -> Int) -> (Store -> Store)_ Recall that have to show that [[pi |- U:theta]] \in Env_pi -> [[theta]] Think about what this means for the define I1(I2:theta2) = U phrases. Q: for the eager semantics? (exercise) ** copy rule for lazily-evaluated parameters (3.3) ------------------------------------------ COPY RULE FOR LAZILY-EVALUATED PARAMETERS (3.3) Idea ... define I1(I2:t) = U ... in ... invoke I1(V) ... ==> ... define I1 = \I2:t.U ... in ... invoke I1(V) ... ==> ... (\I2:t.U)(V) ... ==> ... [V/I2]U ... ------------------------------------------ First introduce parameterized abstractions, consider adding parameters directly sugar (a la Scheme). Then use the Ch 2 copy rule, then need a rule for application of lambda abstractions (beta reduction). *** lambda abstractions ------------------------------------------ LAMBDA ABSTRACTIONS Recall: pi' |- U : t2 ____________________________________ pi |- \I:t1.U : t1 -> t2 where pi' = pi unionMinus {I:t1} Semantics: Parameter copy rule (beta reduction): ------------------------------------------ ... [[pi |- \I:t1.E : t1 -> t2]] e = f, where f v = [[pi' |- E:t2]](e unionMinus {I=v}) pi' = pi unionMinus {I:t1} ... (\I:t.U)(V) ==> [V/I]U this is also an operational semantics Of course, you have to be careful to avoid capture, but we've done this before, so see the book for details. The advantage of this is that lazily evaluated abstractions and parameters both reduce to the core