A Located Lambda Calculus
Total Page:16
File Type:pdf, Size:1020Kb
A located lambda calculus Ezra elias kilty Cooper Philip Wadler University of Edinburgh Abstract how to perform a splitting transformation to produce code for each Several recent language designs have offered a unified language for location. However, each of these works relied on concurrently- programming a distributed system; we call these “location-aware” running servers. Ours is the first work we’re aware of that shows languages. These languages provide constructs that allow the pro- how to implement a located language on top of a stateless server grammer to control the location (the choice of host, for example) model. where a piece of code should run, which can be useful for secu- Our technique involves three essential transformations: defunc- rity or performance reasons. On the other hand, a central mantra tionalization a` la Reynolds, CPS transformation, and a “trampo- of web engineering insists that web servers should be “stateless”: line” that allows tunnelling server-to-client requests within server that no “session state” should be maintained on behalf of individ- responses. ual clients—that is, no state that pertains to the particular point of We have implemented a version of this feature in the Links lan- the interaction at which a client program resides. Thus far, most guage (Cooper et al. 2006). In the current version, only calls to top- implementations of unified location-aware languages have ignored level functions can pass control between client and server. Here this precept, usually keeping a process for each client running on we provide a formalization and show how to relax the top level- the server, or otherwise storing state information in memory. We function restriction. In particular, the current, limited version re- show how to implement a location-aware language on top of the quires just a CPS translation and a trampoline; defunctionalization stateless-server model. is needed in implementing nested annotations. This paper This paper presents a simple λ-calculus enriched with 1. Introduction location annotations, allowing the programmer to indicate the loca- tion where a fragment of code should execute. The semantics of Designing a web server requires thinking carefully about user state this calculus clarifies where each computation step is allowed to and how to manage it. Unlike a desktop application, which deals take place. with one user at a time, or a traditional networked system, which We then give a translation from this calculus to a first-order ab- may handle multuple simultaneous requests but in a more con- stract machine that models an asymmetrical client- server environ- trolled environment, a modest web system can expect to deal with ment, and show that the translation preserves the locative semantics tens or hundreds of thousands of users in a day, each one can have of the source calculus. multiple windows open on the site simultaneously—and these users As a stepping stone to the full translation, we formally define can disappear at any time without notifying the server. This makes defunctionalization. By isolating this phase of the larger translation, it infeasible for a web server to maintain state regarding a user’s we hope to clarify the notation and formal techniques that will session. The mantra of web programming is: Get the state out!— be used in the full translation. While there are many compact get it out of the server and into the client. An efficient web server definitions of CPS transformations in the literature, we did not find will respond to each request quickly and then forget about it even such a compact and formal definition of defunctionalization. We quicker. give a complete formal definition of defunctionalization in eleven Nonetheless, several recent high-level programming language lines. designs allow the programmer the illusion of a persistent environ- ment encompassing both client and server. This allows the pro- 2. Defunctionalization grammer to move control back and forth freely between client and server, using local resources on either side as necessary, but still Source calculus, λsrc expressing the program in one language. Figure 1 shows an entirely pedestrian call-by-value λ-calculus, Murphy et al. (2004) introduced a core located calculus, Lamb- called λsrc, defined with a big-step reduction relation M ⇓ V , da 5, and Murphy (2007) built upon this a full-fledged program- stating that term M reduces to value V . We write N{V/x} for ming language, ML5, also showing how to compile it to separate the capture-avoiding substitution of a value V for the variable x code for client and server. Neubauer and Thiemann (2005) also in- in the term N, and N{V1/x1,...,Vn/xn} for the simultaneous troduced a variant of ML with location annotations and showed capture-avoiding substitution of each Vi for the corresponding xi. We let σ range over such n-ary substitutions. We assume terms are equal up to α-equivalence. First-order machine The defunctionalized machine, DM, defined in Figure 2, is a first- order machine, in contrast to λsrc which allowed expressions in the function position of an application. In DM, terms, ranged over by L, M, and N, are first-order; they are built from constants c, [Copyright notice will appear here once ’preprint’ option is removed.] variables x, constructor applications F (M~ ), function applications 1 2008/4/2 Syntax λx.N = pλx.Nq(~y) ~y = FV(λx.N) constants c J xK = x variables x J K terms L, M, N ::= LM | λx.N | x | c c = c values V, W ::= λx.N | x | c LMJ K = apply( L , M ) J K J K J K Semantics (big-step reduction) coll f LM = f(LM) ∪ coll f L ∪ coll f M V ⇓ V (VALUE) coll f λx.N = f(λx.N) ∪ coll f N coll f V = f(V ) when V 6= λx.N L ⇓ λx.N M ⇓ WN{W/x} ⇓ V (BETA) LM ⇓ V fun,aux λx.N = {pλx.Nq(~y) → N {arg/x}} J K J K where ~y = FV(λx.N) fun,aux Figure 1. Higher-order source, λsrc. M = {} when M 6= λx.N J K M fun = coll − fun,aux M Syntax J K J K top fun variables x, y, z M = letrec apply(fun, arg) = case fun of M J K J K function names f, g constructors F , G Figure 3. Defunctionalization. values V, W, K ::= c | x | F (V~ ) terms M, N ::= c | x | f(M~ ) | ~ ~ −1 −1 ~ −1 F (M) | case M of A F (V ) D = λx.( N{x/arg} ){ V /~y} J K J K J K alternative sets A a set of A items when (F (~y) → N) ∈ cases(apply, D), where x fresh case alternatives A ::= F (~x) → M x −1 = x eval. contexts E ::= [ ] | f(V~ , E, M~ ) | D J K−1 F (V~ , E, M~ ) | case E of A c D = c function def. D ::= f(~x) = M J K−1 −1 −1 apply(L, M) D = L D M D definition set D ::= letrec D and ··· and D J K J K J K Semantics (small-step reduction) Figure 4. An reverse translation for defunctionalization. M −→D N is used by M top to traverse a term: it applies a function f to each J K E[f(V~ )] −→D E[M{V~ /~x}] subterm of its argument, collecting the results. when (f(~x) = M) ∈ D A special feature of our translation is the use of an injective function that maps source terms into the space of constructor E[case (F (V~ )) of A] −→D E[M{V~ /~x}] when (F (~x) → M) ∈ A names. We write pMq for the name assigned to the term M by this function. One example of such a function is the one that col- Figure 2. First-order target, DM (the Defunctionalized Machine). lects the names assigned to immediate subterms and uses a hash function to digest these into a new name. Issues of possible hash collisions would have to be treated delicately. f(M~ ) and case expressions case M of A. A list A of case We also use a reverse translation, or retraction of − , defined alternatives is well-formed if it uniquely maps each name. −1 J K in Figure 4. Here M D denotes the retraction of a DM term M The machine also uses a set D of function definitions. Each has in the context of definitionsJ K D. We lift the reverse translation to the form f(~x) = M, defining a function called f taking parameters substitutions: ~x M which are then bound in the function body . A definition set If σ is {V /x ,...,V /x } is well-formed if it uniquely defines each name. The definitions are 1 1 n n −1 −1 −1 mutually recursive, so scope of each definition extends throughout then σ D is { V1 D /x1,..., Vn D /xn}. J K J K J K all the other definitions as well as the term under evaluation. To extract the alternatives of case-expressions from function bod- The semantics is defined through a small-step reduction rela- ies, we use a function cases, defined as follows. tion M −→D N stating that the term M reduces to the term N in the context of definition-set D. The relation −D is the reflex- Definition 1. Define a meta-function cases that returns the branches ive, transitive closure of −→D, with the definitions D held fixed of a given function when that function is defined by case-analysis. through the reduction sequence. Formally, define cases(f, D) = A Defunctionalization when (f(x, ~y) = case fun of A) ∈ D Defunctionalization is a translation from the terms of λsrc to the terms and definition-sets of DM; it is defined in Figure 3.