SLIDE 1
The RPC Calculus Symmetrical RPC in an Asymmetrical World Ezra - - PowerPoint PPT Presentation
The RPC Calculus Symmetrical RPC in an Asymmetrical World Ezra - - PowerPoint PPT Presentation
The RPC Calculus Symmetrical RPC in an Asymmetrical World Ezra Cooper Philip Wadler September 8, 2009 Dream of unified web programming Dream of unified web programming What we want Reality of web programming Reality of web programming
SLIDE 2
SLIDE 3
Dream of unified web programming What we want
SLIDE 4
Reality of web programming
SLIDE 5
Reality of web programming It’s a bit more fiddly.
SLIDE 6
Reality of web programming It’s a bit more fiddly. Here’s why:
SLIDE 7
Traditional program
SLIDE 8
Traditional program
SLIDE 9
Traditional web program .
SLIDE 10
Traditional web program .
SLIDE 11
Unified program
SLIDE 12
Unified program Simplifies the work of web programming
SLIDE 13
Unified program Simplifies the work of web programming The Links language: http://groups.inf.ed.ac.uk/links
SLIDE 14
Dream of a unified language
Waking up:
◮ Desire to control location explicitly, with a light touch; ◮ Need control for performance and security reasons; ◮ Tricky because of asymmetrical client/server relationship.
SLIDE 15
Roadblock: Asymmetrical client/server relationship
SLIDE 16
Roadblock: Asymmetrical client/server relationship
SLIDE 17
Stateless server
Web applications should not store control state at the server.
SLIDE 18
Stateless server
Web applications should not store control state at the server. Server should encode all state and give it to client.
SLIDE 19
Stateless server
Web applications should not store control state at the server. Server should encode all state and give it to client. For this talk, state = call stack.
SLIDE 20
Example program
fun checkPassword(name, password) { # load this user’s row from database & check password var u = lookupUser(name); u.password == password } fun validate() { var auth = checkPassword(fieldValue(”name”), fieldValue(”password”))); if (auth) displaySecretDocument(); else displayErrorMessage(); }
SLIDE 21
Example located program
fun checkPassword(name, password) server { # load this user’s row from database & check password var u = lookupUser(name); u.password == password } fun validate() client { var auth = checkPassword(fieldValue(”name”), fieldValue(”password”))); if (auth) displaySecretDocument(); else displayErrorMessage(); }
SLIDE 22
Example located program: server push
fun findFlights(flightQuery) server { # Query each vendor for its own matching flights for (vendor ← airlines()) { var flights = queryVendor(vendor, flightQuery); # Send this vendor’s flights to the browser displayFlights(flights); } } fun displayFlights(flights) client { # Add each flight to the page for (flight ← flights) addToPage(flight); }
SLIDE 23
Example: higher-order functions
How should this code behave? fun usernameMap(f ) server { var users = getUsersFromDatabase(); for (u ← users)[f (u.name)] } fun userNameFirstThree() client { usersMap(fun(name){take(3, name)}); }
SLIDE 24
Example: higher-order functions
How should this code behave? fun usernameMap(f ) server { var users = getUsersFromDatabase(); for (u ← users)[f (u.name)] } fun userNameFirstThree() client { usersMap(fun(name){take(3, name)}); }
⊲ Functions in lexical client-context execute on client.
SLIDE 25
What I want to show you
◮ How to compile this language for the asymmetrical
client-server model,
SLIDE 26
What I want to show you
◮ How to compile this language for the asymmetrical
client-server model,
◮ How the compilation factors into standard techniques,
SLIDE 27
What I want to show you
◮ How to compile this language for the asymmetrical
client-server model,
◮ How the compilation factors into standard techniques, ◮ How these these techniques can be presented formally and
concisely.
SLIDE 28
How it’s done
Call to f (server) Call to g (client) Return r from g Return s from f {Call f} {Call g, k} {Continue r, k} {Return s} main Client Server
Source language: call/return style Implementation: request/response style
f g
SLIDE 29
Getting technical
SLIDE 30
Source language: the located lambda calculus
SLIDE 31
Source language: the located lambda calculus
L, M, N ::= LM | λax.N | λx.N | x | c a, b ::= c | s
SLIDE 32
Source language: the located lambda calculus
L, M, N ::= LM | λax.N | λx.N | x | c a, b ::= c | s We eliminate un-located forms λx.N by explicitly copying the location of their lexical context. So λcx.L(λy.N) becomes λcx.L(λcy.N)
SLIDE 33
Source language: the located lambda calculus
L, M, N ::= LM | λax.N | x | c a, b ::= c | s We eliminate un-located forms λx.N by explicitly copying the location of their lexical context. So λax.L(λy.N) becomes λcx.L(λcy.N)
SLIDE 34
Semantics
Read M ⇓a V as ”M evaluates, starting at a, to V .” V ⇓a V (Value) L ⇓a λbx.N M ⇓a W N{W /x} ⇓b V LM ⇓a V (Beta) L ⇓a c M ⇓a W δa(c, W ) ⇓a V LM ⇓a V (Delta)
SLIDE 35
Translation to a client-server system
Three techniques:
◮ CPS translation:
reifies the control state
◮ Defunctionalization:
turns higher-order functions into data (serializable)
◮ Trampolining:
inverts control, so state resides at client.
SLIDE 36
CPS translation (due to Fischer, 1972, via Sabry and Wadler, 1997)
Source: L, M, N ::= LM | V V ::= λx.N | x CPS translation: (LM)†K = L†(λf .M†(λx.fxK)) V †K = KV ◦ (λx.N)◦ = λx.λk.N†k x◦ = x
SLIDE 37
Defunctionalization
SLIDE 38
Defunctionalization target
D ::= letrec D and · · · and D D ::= f ( x) = case x of A A ::= a set of A items A ::= F( c) ⇒ M M ::= f ( M) | F( M) | x | c
SLIDE 39
Defunctionalization target
D ::= letrec D and · · · and D D ::= f ( x) = case x of A A ::= a set of A items A ::= F( c) ⇒ M M ::= f ( M) | F( M) | x | c function names f , g constructor names F, G
SLIDE 40
Defunctionalization (orig. Reynolds, 1972)
[ [M] ]top = letrec apply(fun, arg) = case fun of [ [M] ]fun∗ in [ [M] ] [ [λx.N] ]fun = λx.N( y) ⇒ [ [N] ]{arg/x} where y = fv(λx.N) [ [LM] ] = apply([ [L] ], [ [M] ]) [ [V ] ] = V ◦ (λx.N)◦ = λx.N( y) where y = fv(λx.N) x◦ = x The operation M gives an opaque identifier for the term M.
SLIDE 41
Trampolining (due to Ganz, Friedman and Wand)
◮ Continually returns control to a top-level trampoline; ◮ Works on any tail-form program,
including CPS programs;
◮ Choice of the trampoline modifies the behavior.
SLIDE 42
Trampolining
(LM)T = Bounce(λz.LtMt) (where z is a dummy) V T = Return(V t) (λx.N)t = λx.NT xt = x Behavior depends on our choice of tramp.
SLIDE 43
Example trampolines
Trivial trampoline: tramp(x) = case x of Bounce(thunk) ⇒ tramp(thunk()) | Return(x) ⇒ x
SLIDE 44
Example trampolines
Trivial trampoline: tramp(x) = case x of Bounce(thunk) ⇒ tramp(thunk()) | Return(x) ⇒ x Step-counting trampoline: tramp(n, x) = case x of Bounce(thunk) ⇒ print(n); tramp(n + 1, thunk()) | Return(x) ⇒ x
SLIDE 45
Our trampoline
Since the control state is reified, tramp can split the computation into a client- and a server-side piece. tramp(x) = case x of | Bounce(f , x, k) ⇒ tramp(req cont (k, apply(f , x))) | Return(x) ⇒ x (This shouldn’t make sense yet; don’t worry.)
SLIDE 46
Our trampoline
Since the control state is reified, tramp can split the computation into a client and a server-side piece. tramp(x) = case x of | Call(f , x, k) ⇒ tramp(req cont (k, apply(f , x))) | Return(x) ⇒ x (This shouldn’t make sense yet; don’t worry.)
SLIDE 47
The Big Transformation
SLIDE 48
First, the target: first-order client-server calculus
SLIDE 49
The client-server calculus
Syntax configurations K ::= (M; ·) | (E; M) terms L, M, N ::= x | c | F( M) | f ( M) | req f ( M) definition set D, C, S ::= letrec D and · · · and D function definitions D ::= f ( x) = case M of A alternative sets A a set of A items case alternatives A ::= F( x) ⇒ M function names f , g constructor names F, G
SLIDE 50
Configurations of the machine
SLIDE 51
Semantics
Client: (E[f ( V )]; ·) − →C,S (E[M{ V / x}]; ·) if (f ( x) = M) ∈ C (E[case (F( V )) of A]; ·) − →C,S (E[M{ V / x}]; ·) if (F( x) ⇒ M) ∈ A Server: (E; E ′[f ( V )]) − →C,S (E; E ′[M{ V / x}]) if (f ( x) = M) ∈ S (E; E ′[case (F( V )) of A]) − →C,S (E; E ′[M{ V / x}]) if (F( x) ⇒ M) ∈ A Communication: (E[req f ( V )]; ·) − →C,S (E; f ( V )) (E; V ) − →C,S (E[V ]; ·)
SLIDE 52
Now, the translation
SLIDE 53
Transformation on terms
(λax.N)◦ = λax.N( y)
- y = fv(λax.N)
x◦ = x c◦ = c V ∗ = V ◦ (LM)∗ = apply(L∗, M∗) V †[ ] = cont([ ], V ◦) (LM)†[ ] = L†(M( y, [ ])) where y = fv(M)
SLIDE 54
Transformation to definitions (client-side)
[ [M] ]c,top = letrec apply(fun, arg) = case fun of [ [M] ]c,fun and tramp(x) = case x of | Call(f , x, k) ⇒ tramp(req cont (k, apply(f , x))) | Return(x) ⇒ x [ [λcx.N] ]c,fun = λcx.N( y) ⇒ N∗{arg/x} where y = fv(λx.N) [ [λsx.N] ]c,fun = λsx.N( y) ⇒ tramp(req apply (λsx.N( y), arg, Fin())) where y = fv(λx.N)
SLIDE 55
Transformation to definitions (server-side)
[ [M] ]s,top = letrec apply(fun, arg, k) = case fun of [ [M] ]s,fun and cont(k, arg) = case k of [ [M] ]s,cont | App(fun, k) ⇒ apply(fun, arg, k) | Fin() ⇒ Return(arg) [ [λsx.N] ]s,fun = λsx.N( y) ⇒ (N†k){arg/x} where y = fv(λx.N) [ [λcx.N] ]s,fun = λcx.N( y) ⇒ Call(λcx.N( y), arg, k) where y = fv(λx.N) [ [LM] ]s,cont = M( y, k) ⇒ M†(App(arg, k)) where y = fv(M)
SLIDE 56
Correctness: Bisimulation
M ⇓
✲ V
M′ − ։ ✲ V ′ M ⇓
✲ V
M′ − ։ ✲ V ′
SLIDE 57
Summary
We can
SLIDE 58
Summary
We can
◮ Enrich a functional programming language with location
annotations,
SLIDE 59
Summary
We can
◮ Enrich a functional programming language with location
annotations,
◮ which designate execution location of their contents lexically,
SLIDE 60
Summary
We can
◮ Enrich a functional programming language with location
annotations,
◮ which designate execution location of their contents lexically, ◮ and whose semantics are straightforward,
SLIDE 61
Summary
We can
◮ Enrich a functional programming language with location
annotations,
◮ which designate execution location of their contents lexically, ◮ and whose semantics are straightforward, ◮ and we can execute these programs on an asymmetrical
client-server system with a “stateless server”
SLIDE 62
Summary
We can
◮ Enrich a functional programming language with location
annotations,
◮ which designate execution location of their contents lexically, ◮ and whose semantics are straightforward, ◮ and we can execute these programs on an asymmetrical
client-server system with a “stateless server”
◮ using a combination of classic transformations.
SLIDE 63