120 likes | 258 Views
CS711 Foundational PCC part 2. Greg Morrisett Cornell University. Recall: FPCC. Define the semantics of types in terms of the machine's instructions & security policy: e.g., v in ptr(T) (m) =def= readable(v) & v in a & m(v) in T(m)
E N D
CS711Foundational PCC part 2 Greg Morrisett Cornell University
Recall: FPCC • Define the semantics of types in terms of the machine's instructions & security policy: • e.g., v in ptr(T) (m) =def= readable(v) & v in a & m(v) in T(m) • When v inhabits a type t, then the definition of that type lets you use the value effectively. • e.g., read through the pointer safely • You've effectively defined the type as the inference rule. • But in this context, you have to prove that v has these properties to assert it has this type. Lang. Based Security
Validity • The semantics is sensitive to a particular machine state, so updates are problematic • v has type t in state m • problem is reestablishing this on update(m,e1,e2) • Valid types are those that preserve certain global invariants needed to reason effectively in the presence of updates. • e.g., once allocated, the type of a location stays the same. • But now types have to be parameterized by the set of allocated values: v in T(a,m) • Most type constructors are valid. Lang. Based Security
Recursive Types When we have a recursive type: T =def= (.char + * + ) datatype T = Char of char | Pair of T*T | Fn of TT we run into problems. • Semantics of (F) is taken as the least fixed point of F. Gives us solution to (F) = F((F)). • But to ensure lfp exists, need F to be monotone w.r.t. subtyping. • Not the case in the above due to the • Recall that subtyping is contra-variant (i.e., anti-monotonic) on the left of an arrow type. Lang. Based Security
McAllester & Appel • Trick 1: use "operational" denotational sem. • types interpreted as sets of terms • in particular, T1T2 is not taken to be the set of (mathematical) functions from T1 to T2 • Trick 2: Typings indexed by number k: • v :k T means v behaves like a T for at least k steps of the machine. • v :k T1T2 is downward closed on k • That is, we only have to consider arguments v' such that v1 :j T1 where j < k and produce a result v2 :j T1. • So is monotonic for both argument and result type. • interpret as lfp w.r.t. k instead of subtyping Lang. Based Security
Pros and Cons • Pros • all the type constructors we need • e.g., recursive types, general refs, etc. • no need to master domain theory • simple lfp interpretation for recursive types • semantics generalizes to PER model • gives us a mechanism for proving equivalence • Cons • Draws more distinctions than a domain-theoretic account because it bakes in the abstract machine. • Can it be used to relate a source & target language with a non-trivial connection in their abstract machines? Lang. Based Security
Indexed Types for LC • e ::= x | 0 | (e1,e2) | i e | x.e | e1 e2 • v ::= 0 | (v1,v2) | x.e • standard small-step operational sem. • standard type inference rules plus: G|- e : (F) G|- e : F((F)) • type T is a set of pairs (k,v) • k is a natural, v a value • downward closed: (k,v) in T implies for all j s.t. 0 <= j <= k. (j,v) in T • more properly, the value interpretation of a type • note: definition is outright using syntactic terms Lang. Based Security
Expression Interpretation • e :k T when e is a closed expression: • e does not get stuck within k steps and • if e j v for j < k and some v, then (k-j,v) is in T. • intuitively: e behaves like a T for k steps • Note: e :k T implies e :k-j T • Also, for any e and T, e :0 T • And (k,v) in T v :k T Lang. Based Security
Semantic Type Constructors • Bot = {} • Top = {(k,v) | k >= 0} • int = {(k,0) | k >= 0}| • T1 x T2 = {(k,(v1,v2)) | All j < k.(j,vi) in Ti} • T1 T2 = {(k,(x.e)) | All j < k. All v. (j,v) in T1 => e[v/x] :j T} • (F) = {(k,v) | (k,v) in Fk+1(Bot)} Lang. Based Security
Extension to Open Terms • Given a substitution of s mapping variables to closed terms, we say s :kG if for all x in Dom(G). s(x) :k G(x) • Say G |=k e : T when for all s s.t. s :kG, s(e) :k T. • Say G |=e : T when for all k, G |=k e : T. • Easy implication: |=e : T implies e safe. • Critical theorem: If G |-e : T then G |=e : T • proof is by induction on the derivation of G |-e : T. Lang. Based Security
Interesting: (F) = F((F)) • approx(k,T) = {(j,v) | j < k & (j,v) in T} • well-founded function F is such that:approx(k+1,F(T)) = approx(k+1,F(approx(k,T))) • F well founded an j < k implies: • approx(j,Fj(T1)) = approx(j,Fj(T2)) • approx(j,Fj(T1)) = approx(j,Fk(T2)) • F well founded implies • (F) a type (i.e., downward closed.) • yada yada yada... • (F) = F((F)) Lang. Based Security
Nonexpansive • approx(k,F(T)) = approx(k,F(approx(k,T)) • i.e., nothing happens when you go around the loop • Every well-founded F is non-expansive. • good news, most functors work out... Lang. Based Security