DEFINITION OF GALOIS CONNECTION Def: Suppose that L is partially ordered by <=, and M is partially ordered by \sqsubseteq, a : L -> M, and g : M -> L, then (a,g) is a *Galois connection* iff for all l \in L, m \in M :: a(l) \sqsubseteq m iff l <= g(m) Corollary (p. 232 in the textbook): Suppose that (a,g) is a Galois connection between (L,<=) and (M,\sqsubseteq), then for all l \in L, m \in M:: l <= g(a(l)) (4.8) and a(g(m)) \sqsubseteq m (4.9) Corollary: If (a,g) is a Galois connection, then a preserves existing lubs and g preserves existing glbs GALOIS CONNECTION PROPERTIES Lemma: g(\bigsqcup_{i \in \Delta} T_i) = \bigsqcap_{i \in \Delta} g(T_i)). Corollary. If g is such that g(\bigsqcup_{i \in \Delta} T_i) = \bigsqcap_{i \in \Delta} g(T_i)), then there is a unique (upper) adjoint a : Prop -> PT such that (a, g) is a Galois connection. CONSEQUENCES If P is a property (set of values), then a(P) is the most precise type of programs with property P Implications of program properties is abstracted by superset inclusion: E.g., let oddInt = {1, 3, 5, ...} int = {1,2,3,4, ...} then oddInt \subseteq int and g(int) \supseteq g(oddInt) MONOTYPE SEMANTICS T : E -> PT T[[x]] = {(H,H(x)) | H \in |H} T[[fn x ==> e]] = T[[e1(e2)]] = {(H, m2) | (H, m1->m2) \in T[[e1]], (H, m1) \in T[[e2]]} T[[rec f . fn x ==> e]] = T[[1]] = {(H,int) | H \in |H } T[[e1 - e2]] = {(H,int) | (H,int) \in T[[e1]] \cap T[[e2]]} T[[(e1 ? e2 : e3)]] = {(H,m) | (H,int) \in T[[e1]], (H,m) \in T[[e2]] \cap T[[e3]]} SOUNDNESS def: The type semantics T[[.]] is *sound* iff for all programs e \in E :: S[[e]] \in g(T[[e]]) Corollary: (With the conventions above) S[[e]] \in g(T[[e]]) iff a(C[[e]]) \supseteq T[[e]] iff C[[e]] \subseteq g(T[[e]]). Corollary (soundness): Let e \in E be a program, and let H be a type environment. Then typeable programs cannot go wrong in the sense that: (H,m) \in T[[e]] and r \in g2(H) and S[[e]](r) \neq \bot implies S[[e]](r) \neq \Omega POLYTYPE SYNTAX m \in M "monotype" m ::= int | m1 -> m2 p \in |P = PowerSet(M) "polytype" H \in H "type environment" = X ->_{fin} P t \in I = H x M "typing" T \in PT = PowerSet(I) "program type" MEANINGS OF TYPES concretization function for monotypes: g1: M -> PowerSet(U) g1(int) = {up(z)::Z_{\bot} | z \in Z} \cup {\bot} g1(m1 -> m2) = {up(\phi)::[U->U]_{\bot} | \phi \in [U -> U], (\forall u \in g1(m1) :: \phi(u) \in g1(m2))} \cup {\bot} for polytypes: g2: P -> PowerSet(U) g2(p) = \bigcap_{m \in p} g1(m) g2(\emptyset) = U for type environments: g3: H -> PowerSet(R) g3(H) = {r \in R | (\forall x \in X :: r(x) \in g2(H(x)))} for typings: g4 : I -> Prop g4((H,m)) = {\phi \in S | (\forall r \in g3(H) :: \phi(r) \in g1(m))} for program types: g : PT -> Prop g(T) = \bigcap {g4(\theta) | theta \in T} g(\emptyset) = S POLYMORPHIC TYPING T : E -> PT T[[x]] = {(H,m) | m \in H(x)} T[[fn x ==> e]] = {(H, m1->m2) | (H[x<-m1],m2) \in T[[e]]} T[[e1(e2)]] = {(H,m2) | (H,m1->m2) \in T[[e1]], (H,m1) \in T[[e2]]} T[[let x = e1 in e2]] = {(H,m2) | (e\xists p1 \neq {} : m1 \in p1 : (H,m1) \in T[[e1]] and (H[x<-p1],m2)\in T[[e2]])} T[[rec f . fn x ==> e]] = T[[1]] = {(H,int) | H \in |H } T[[e1 - e2]] = {(H,int) | (H,int) \in T[[e1]] \cap T[[e2]]} T[[(e1 ? e2 : e3)]] = {(H,m) | (H,int) \in T[[e1]], (H,m) \in T[[e2]] \cap T[[e3]]} ABSTRACT SEMANTICS Def: an *abstract domain* is specified by a poset, (T#,<=#), and an abstract semantic function, T# : E -> T#. Def: An abstract semantics (T#,<=#) and T# is *compositional* iff for all e \in E : e = [x1,...,xn](e1,...,en) where the xi \in X are locally bound, and the ei \in E are subexpression : T#[[e]] = \Psi#_e(T#[[e1]],...T#[[en]]) so that T# is defined compositionally based on the primitives \Psi#_e. Def: A compositional abstract semantics is monotone when all primitives are monotone, i.e., (T1,...,Tn) <=#(T1',...,Tn') ==> (\Psi#_e(T1,...,Tn) <=# \Psi#_e(T1',...,Tn')) Def: A monotone compositional abstract semantics is an *abstract interpreter* when the abstract domain (T#,<=#) is representable (in a computer). ABSTRACTION Def: An abstract semantics, with abstract domain (T#,<=#) and abstract semantic function T# is an *abstraction* of a (concrete) semantics (Tb,<=b) (with semantic function Tb) iff there is a concretization map g : T# -> Tb that is monotone and such that for all e \in E :: Tb[[e]] <=b g(T#[[e]]). Def: An abstract semantics is *sound* if it is an abstraction of the collecting semantics. DESIGN OF AN ABSTRACT INTERPRETER A. Find a Galois connection (a,g) from the collecting semantics (Tb,<=b) to a suitable property space (T#,<=#) B. Find a set of primitives, Pb and P# that are all monotone. C. Check these make a monotone compositional abstraction: forall e \in E :: a(\Psib_e(Tb[[e1]],...,Tb[[en]])) <=# \Psi#_e(a(Tb[[e1]]), ...,a(Tb[[en]])) D. For each e \in E, calculate \Psi#_e, starting from \Psi#_e(a(Tb[[e1]]), ...,a(Tb[[en]])) (approximating when necessary)