Com S 641 meeting -*- Outline -*- * Expression abstractions, i.e., functions (2.1) ** abstract syntax Besides Declarations and Identifiers, add Programs, allow grouping declarations at beginning (instead of mixing them in) ------------------------------------------ CORE IMPERATIVE LANGUAGE WITH NAMES (WhileN) Abstract Syntax: C \in Command P \in Program E \in Expression D \in Declaration L \in Location I \in Identifier N \in Numeral P ::= D ::= C ::= L := E | skip | C1 ; C2 | if E then C1 else C2 fi | while E do C od E ::= N | @L | E1 + E2 | not E | E1 = E2 | L ::= loc i, if i > 0 N ::= n, if n \in Integer Example: ------------------------------------------ ... P ::= D in C D ::= fun I = E | D1 ; D2 | D1 , D2 E ::= ... | I Point out both declaration and invocation forms The D1;D2 form means sequential declaration, D1,D2 means simultaneous an illegal (it will turn out) but illustrative example (fun z = 0; fun z = 3, fun x = z+1) in x Q: What comes next in our description technique? ** type rules *** type assignments ------------------------------------------ TYPE ASSIGNMENTS Does the following type check? loc 1 := 3 + id def: a *type assignment* is a set of Examples: ------------------------------------------ ... It depends on the context (assumptions) fun id = 4 in loc 1 := 3 + id : comm fun id = (4 = 4) in loc 1 := 3 + id : ? think of a logic: does 2+2+1 = x+1?, yes, if we assume x = 2+2, Q: What information do we need to type check it? ... (identifier, type) pairs But we think of this as a (partial) mapping from identifiers to types Q: How could we model this in Haskell? type TypeAssign = [(Identifier, TypeAttrib)] Notation for these is \pi. sometimes called type environments, type contexts,... *** information flow ------------------------------------------ INFORMATION FLOW IN TYPE RULES I N:int L:int loc I fun id = 4 in loc 1 := id ------------------------------------------ the I in a declaration doesn't get an attribute, but the use does. Why, we don't know what type it is yet. Show the formation of D:{id:int exp}dec, the dec means "declaration" call that pi_0, then use that on the right side How can we show that? use \pi_0 |- I:int exp borrowing notation from logic ("|-" is "proves") Can a declaration depend on a type assignment? yes, so put in the \emptyset |- D:{id:int exp}dec notation. Q: Look at the |- symbols, which way does the information flow on either side of them? down the tree on the left = inherited attributes (t.a.'s) up the tree on the right = synthesized attributes (types) so you also can read \pi |- U:t as if we inherit \pi, then we synthesize t *** actual rules ------------------------------------------ PROGRAM TYPING RULE _________________________________ |- D1 in C: comm DECLARATION TYPING RULES _________________________________ |- fun I = E : {I: }dec _________________________________ \pi |- D1,D2 : _________________________________ \pi |- D1;D2 : where ------------------------------------------ explain the \uniondot and \unionminus notation ... p1 \unionDot p2 = p1 \union p2 if the ranges are disjoint and is undefined otherwise (an error) ... p1 \unionMinus p2 = {(I:theta) | (I:theta) \in p2 or I \not\in dom(p2) and (I:theta) \in p1} Note: the rule for D1;D2 in the book is wrong, in that it doesn't treat the surrounding context correctly. It should be ... \pi |- D1:\pi_1 dec, \pi \unionMinus \pi_1 |- D2: \pi_2 dec if disjoint \pi_1 \pi_2 __________________________________________ \pi |- D1;D2 : (\pi_1 \uniondot \pi_2) dec Q: Why use mini-environments as the result of declarations? otherwise would get spurious conflicts, e.g., in fun x = 3; (fun y = 4, fun z = 5) this allows more flexibility in combining them Q: How could we allow overriding in sequential declarations? use \unionMinus in both spots Q: how should we revise the rules for expressions? pass in the type assignment Q: why do we need that because identifiers are expressions? give rule for E1 + E2, and for I tell them to look at figure 2.3 ** semantics (2.2) Q: In the semantics of expressions, how do we find the values of identifiers? need something like a type assignment, called an environment... ------------------------------------------ ENVIRONMENTS Environment = Set of Examples: OLD SEMANTIC DOMAINS [[C:comm]] \in Store -> Store [[E:t exp]] \in Store -> [[t]] NEW SEMANTIC DOMAINS [[\pi |- C:comm]] \in [[\pi |- E:t exp]] \in ------------------------------------------ ... (Identifier, Meaning) pairs ... env from {(x, \ s -> 5)} fun x = 5 {(id, \s -> 4), (b, \s -> lookup(1, s))} fun id = 4, fun b = @loc 1 Q: How would you model environments in Haskell? type DEnvironment = [(Identifier, DenotableValue)] ... Environment -> Store -> Store ... Environment -> Store -> [[t]] use e as prototypical environment, s for a store ------------------------------------------ SEMANTIC FUNCTIONS For expression: [[ |- E1 + E2: int exp]] e s = [[ |- I: t exp ]] e s = Example calculation: let pi1 = {b:int exp}, e1 = {b = \s -> lookup(1, s)}, s777 = [7,7,7] [[pi1 |- loc 3 := b : comm]] e1 s777 = update([[pi1 |- loc 3 : int loc]] e1, [[pi1 |- b : int exp]] e1 s777, s777) = update(3, = ------------------------------------------ ... plus([[\pi |- E1: int exp]]e s, [[\pi |- E2: int exp]]e s) ... v(s), where (I, v) \in e Note that "(I = v) \in e" in the book really means "(I,v) \in e" Note: what we get back is a new store, no new environment Q: Why don't we get back a new environment? because no declaration happening... go over figure 2.4 *** meaning of type attributes (soundness, section 2.3) ------------------------------------------ TYPE ATTRIBUTES theta ::= t exp | int loc | comm | pi dec t ::= int | bool pi ::= {j:theta_j} j \in J, where J finite and J \sub Identifier MEANINGS [[t exp] = Store -> [[t]] [[comm]] = Store -> Store [[bool]] = Bool [[int]] = Int [[int loc]] = Location [[pi dec]] = [[{j:theta_j} ]] = j \in J ------------------------------------------ ... Store -> [[pi]] Why is the store needed? Look back at the rules. ... {j:[[theta_j]]} j \in I Q: What would it mean for the type rules to be sound? have to get pi and e in the statement, can we do that for arbitrary pi and e? Go over some of the cases for soundness (base cases especially) Will need definition of argeement Env_pi = { e | for all j \in J, (j,v) \in e iff there is some theta_j such that (j,theta_j) \in pi and v \in [[theta_j]] } Def: e agrees with pi iff e \in Env_pi