tive driver RD, signal w2 connects RA with a backup driver BD. If no failure arises, ..... in the structure of the langu
Session-based Concurrency, Reactively (Extended Version) Mauricio Cano1 , Jaime Arias2 , and Jorge A. Pérez1 1
University of Groningen
2
Inria Grenoble Rhône-Alpes
Abstract. This paper concerns formal models for the analysis of communication-centric software systems that feature declarative and reactive behaviors. We focus on session-based concurrency, the interaction model induced by session types, which uses (variants of) the π-calculus as specification languages. While well-established, such process models are not expressive enough to specify declarative and reactive behaviors common in emerging communication-centric software systems. Here we propose the synchronous reactive programming paradigm as a uniform foundation for session-based concurrency. We present correct encodings of session-based calculi into ReactiveML, a synchronous reactive programming language. Our encodings bridge the gap between process specifications and concurrent programs in which session-based concurrency seamlessly coexists with declarative, reactive, timed, and contextual behaviors.
1
Introduction
In this paper, we introduce the synchronous reactive programming paradigm as a practical foundation for communication-centric software systems. Our motivation is twofold. First, synchronous reactive programming allows us to uniformly integrate point-to-point communications (as in the π-calculus) with declarative, reactive, timed, and contextual behaviors—this is an elusive combination for process models such as the π-calculus. Second, by relying on ReactiveML (a synchronous reactive programming language with a formal semantics), we may bridge the gap between π-calculus processes and actual concurrent programs, thus bringing a rigorous communication model to programmers. Large software systems are deployed as aggregations of distributed interacting components, which are built using a myriad of different programming platforms and/or made available as black-boxes that expose minimal interaction interfaces. In these complex, heterogeneous systems communication emerges as the key unifying glue. Certifying that interacting components conform to their prescribed protocols is thus an important but challenging task, and is essential in ensuring overall system correctness. Besides protocol conformance, analyzing communication-centric software systems entails addressing additional challenges, which can be seen as related to the increasing ubiquity of these systems. Indeed, communication-centric software appears in emerging trends (e.g., collective adaptive systems) and as such is subject to various classes of requirements that are orthogonal to communication correctness. We focus on communication-centric software systems featuring declarative, reactive, timed, and contextual behaviors. (In §2 we illustrate these intended systems, using a transactional protocol 1
subject to failures.) By stipulating governing conditions (rather than how to implement such conditions), declarative approaches naturally specify, e.g., security policies. Closely intertwined, constructs modeling reactivity, time, and context-awareness are at the heart of mechanisms that enforce, e.g., self-adaptation and fault-tolerance in dependable systems. Therefore, while not directly connected to protocol specifications, declarative, reactive, timed, and contextual behaviors (and their interplay) do influence communication and should be integrated into the analysis of protocol conformance. Process calculi (such as the π-calculus [18]) have long offered a principled basis for the compositional analysis of message-passing programs. Within these approaches, our work concerns session-based concurrency, the interaction model induced by session types [12], which organize protocols as sessions between two or more participants. In session-based concurrency, a session type describes the contribution of each partner to the protocol. Interactions are structured, and always occur in matching pairs; e.g., when one partner sends, the other receives; when one partner offers a selection, the other chooses. Different session type theories for binary (two-party) and multiparty protocols have been developed [13]; here we focus on binary sessions. Binary and multiparty session types rely on π-calculi with session constructs. These session calculi have been extended with declarative, reactive, timed, and contextual behaviors, but none of these extensions captures all these features. For instance, session calculi with assertions (logical predicates) [5,3] may describe certain declarative requirements, but do not account for reactive and contextual behaviors. Frameworks with time-related conditions, such as [4,1], have similar limitations. The framework in [14] supports contextual information through events, but does not represent reactive, declarative behaviors. Integrating these extensions into a single process framework seems rather difficult, for they rely on different languages and often conflicting assumptions. Here we pursue a different approach: we embed session-based concurrency within the synchronous reactive programming (SRP) model for reactive, timed systems [2,11]. Hence, rather than extending session π-calculi with declarative, reactive, timed, and contextual features, we encode session-based communication into a setting where these features (and their interplay) are already well understood. We consider ReactiveML, a programming language based on SRP [17,16], as target language in our developments. ReactiveML is a general purpose functional language with a well-defined formal semantics. Our technical contributions are two correct encodings of session π-calculi into ReactiveML. In a nutshell, we use signals in ReactiveML to mimick names in session π-calculi. Our encodings enable us to integrate, in a seamless and uniform way, session-based constructs as “macros” in ReactiveML programs with declarative and reactive constructs. Moreover, since our encodings are executable (well-typed) ReactiveML programs, our results have a direct practical character, which serves to bridge the gap between specifications in process models and actual concurrent programs. This paper is structured as follows. §2 illustrates our approach via an example. §3 summarizes the syntax and semantics of a session π-calculus and of ReactiveML. In both cases, we consider languages with synchronous and asynchronous (queue-based) communication. §4 presents our two encodings and states their correctness. §5 collects closing remarks. The appendix includes further examples and technical details (omitted definitions and proofs). 2
2
A Motivating Example
We use a toy example to illustrate (i) the limitations of session π-calculi in representing structured communications with declarative/reactive behaviors, and (ii) how our approach, based on encodings into ReactiveML, can neatly overcome such limitations. A Ride Protocol. Suppose a conference attendee who finds himself in a foreign airport. To get in time for his presentation, he uses a mobile app in his phone to request a ride to the conference venue. The intended protocol may be intuitively described as follows: 1. Attendee sends his current location and destination to a neighbouring Driver. 2. Driver receives these two pieces of information and offers three options to Attendee: a ride right now, a ride at a later time, or to abort the transaction. 3. Attendee is in a hurry, and so he selects to be picked up right now. 4. Driver replies by sending an estimated arrival time at Attendee’s location. Using session π-calculus processes (as in, e.g., [19]), this protocol may be implemented as a process S = (νxy)(A(x) | D(y)), where processes A(x) and D(y), abstract the behavior of Attendee and Driver as follows: A(x) = xhloci.xhdesi.x / now.x(e).0 D(y) = y(l).y(d).y . {now : yhetai.0 , later : y(t).yhoki.0 , quit : Closey } where process Closey denotes an unspecified sub-protocol for closing the transaction. Above, we write xhzi.P (resp. x(w).P ) to denote the output (resp. input) along name x with continuation P . Processes x / l.P and x . {li : Pi }i∈I denote internal and external labeled choices, respectively. Above, now, later, and quit denote labels. Process 0 denotes inaction. Process (νxy)P declares x and y as dual session endpoints in P . This way, S says that A(x) and D(y) play complementary roles in the session protocol. The Need for Richer Behaviors. Session-based concurrency assumes that once a session is established, communication may proceed without interruptions. This is unrealistic in most real-life scenarios, where established sessions are prone to failures or interruptions. For instance, a connectivity issue in the middle of the protocol with Driver may leave Attendee stuck in the airport. In such cases, notions of contextual information, reactivity, and time become essential: Contextual Information such as, e.g., external events signalling a malfunction, allows relating the system with its environment. For instance, we may like to relate A(x) and D(y) with a connectivity manager that triggers warning events. Reactivity serves to detect unforeseen circumstances (e.g., failures) and to define appropriate system behaviors to run in such cases. For instance, we may like to define A(x) so that another driver is requested if a failure in a protocol with D(y) arises. Time allows to track the instant in which a failure occurred, and also to establish a deadline within which the failure should be resolved. For instance, in case of failure A(x) may try contacting alternative drivers only until k instants after the failure. As mentioned above, the session π-calculus does not support these features, and proposed extensions do not comprehensively address them. We rely on synchronous reactive programming (SRP) and ReactiveML, which already have the ingredients for seamlessly integrating declarative, reactive behavior into session-based concurrency. 3
ReactiveML. ReactiveML extends OCaml with reactive, timed behavior. Time is modelled as discrete units, called instants; reactivity arises through signals, which may carry values. In ReactiveML, expression signal x in e declares a new signal x. We use constructs emit s v and await s(x) in e to emit and await a signal s, respectively. Preemption based on signals is obtained by the expression do (e1 ) until s → (e2 ), which executes e1 until signal s is detected, and runs e2 in the next instant. Moreover, ReactiveML can encode the parallel composition of expressions e1 and e2 , denoted e1 k e2 . Embedding Sessions in ReactiveML. Our first encoding, denoted J·Kf (cf. Def. 14), translates session π-calculus processes into ReactiveML expressions; we use substitution f to represent names in the session π-calculus using (fresh) signals in ReactiveML. Our second encoding, denoted ([·]) (cf. Def. 17), supports an asynchronous semantics. We illustrate J·Kf by revisiting our example above. Let us define a concurrent reactive program in which JA(x)Kf , JD(y)Kf , and JD0 (w)Kf represent ReactiveML snippets that implement session-based communication. We consider a simple possibility for failure: that Driver (D(y)) may cancel a ride anytime or that communication with Attendee (A(x)) fails and cannot be recovered. Ideally, we would like a new driver D0 (w), whose implementation may be the same as D(y), to continue with the protocol, without disrupting the protocol from the perspective of A(x). This could be easily expressed in ReactiveML as the expression S 0 = signal w1 , w2 in (RA k RD) where: RA = do (JA(x)K{x←w1 } ) until f ail → (await w2 (z) in JA(x)K{x←z} ) RD = do (JD(y)K{y←w1 } ) until f ail → (BD) BD = signal w3 in (emit w2 w3 ; JD0 (w)K{w←w3 } )
S 0 declares two signals: while signal w1 connects a reactive attendee RA and the reactive driver RD, signal w2 connects RA with a backup driver BD. If no failure arises, RA and RD run their expected session protocol. Otherwise, the presence of signal f ail will be detected by both RA and RD: as a result, the attendee will await a new signal for restarting the session; process JD(y)K stops and BD will become active in the next instant. After emitting a fresh signal w3 , BD can execute the protocol with RA.
3
Preliminaries
A Session π-calculus Our presentation follows closely that of [19]. We assume a countable infinite set of variables Vs , ranged over by x, y, . . .. A variable represents one of the two endpoints of a session. We use v, v 0 , . . . to range over values, which include variables and the boolean constants tt, ff. Also, we use l, l0 , . . . to range over labels. We write x e to denote a finite sequence of variables (and similarly for other elements). Definition 1 (π). The set π of session processes is defined as: P, Q ::= xhvi.P | x(y).P | x / l.P | (νxy)P | ∗ x(y).P
| x . {li : Pi }i∈I | v? (P ) : (Q) | P | Q | 0
Process xhvi.P sends value v over x and then continues as P ; dually, process x(y).Q expects a value v on x that will replace all free occurrences of y in Q. Processes x/lj .P and x . {li : Qi }i∈I define a labeled choice mechanism, with labels indexed by the finite set I: given j ∈ I, process x / lj .P uses x to select lj and trigger process Qj . 4
bC OMc (νxy)(xhvi.P | y(z).Q) −→ (νxy)(P | Q{v/z}) bS ELc (νxy)(x / lj .P | y . {li :Qi }i∈I ) −→ (νxy)(P | Qj ) (j ∈ I) bR EPc (νxy)(xhvi.P | ∗ y(z).Q) −→ (νxy)(P | Q{v/z} | ∗ y(z).Q) bI F Tc tt? (P ) : (Q) −→ P
bI F Fc ff? (P ) : (Q) −→ Q
Fig. 1. Reduction relation for π processes (contextual congruence rules omitted).
We assume pairwise distinct labels. The conditional process v? (P ) : (Q) behaves as P if v evaluates to tt; otherwise Qn it behaves as Q. Parallel composition and inaction are standard. We often write i=1 Pi to stand for P1 | · · · | Pn . The double restriction (νxy)P binds together x and y in P , thus indicating that they are the two endpoints of a session. Process ∗ x(y).P denotes a replicated input process, which allows us to express infinite server behaviors. In x(y).P (resp. (νyz)P ) occurrences of y (resp. y, z) are bound with scope P . The set of free variables of P , denoted fv(P ), is as expected. The operational semantics for π is given as a reduction relation −→, the smallest relation generated by the rules in Fig. 1. Reduction expresses the computation steps that a process performs on its own. It relies on a structural congruence on processes, denoted ≡S , which identifies processes up to consistent renaming of bound variables, denoted ≡α . Formally, ≡S is the smallest congruence that satisfies the axioms: P | 0 ≡S P P | Q ≡S Q | P P ≡S Q if P ≡α Q (P | Q) | R ≡S P | (Q | R) (νxy)(νwz)P ≡S (νwz)(νxy)P (νxy)0 ≡S 0 (νxy)P | Q ≡S (νxy)(P | Q) if x, y 6∈ fv(Q) We briefly comment on the rules in Fig. 1. Reduction requires an enclosing restriction (νxy)(· · · ); this represents the fact that a session connecting endpoints x and y has been already established. Rule bC OMc represents the synchronous communication of value v through endpoint x to endpoint y. While Rule bS ELc formalizes a labeled choice mechanism, in which communication of a label lj is used to choose which of the Qi will be executed, Rule bR EPLc is similar to Rule bC OMc, and used to spawn a new copy of Q, available as a replicated server. Rules bI F Tc and bI F Fc are self-explanatory. Rules for reduction within parallel, restriction, and ≡S (not given in Fig. 1) are as expected. The following notion will be useful in stating properties of our translations. Definition 2 (Contexts for π). The syntax of (evaluation) contexts in π is given by the following grammar: E ::= [·] | E | P | P | E | (νxy)(E), where P is a π process and ‘[·]’ represents a ‘hole’. We write C[·] to range over contexts (ν x eye)([·] | P1 | . . . | Pn ), with n ≥ 1. E[P ] (resp. C[P ]) will denote the process obtained by filling [·] with P . An Asynchronous Session π-calculus (aπ) Following [14], we now define aπ, a variant of π with asynchronous (queue-based) semantics. The syntax of aπ includes variables x, y, . . . and co-variables, denoted x, y. Intuitively, x and x denote the two endpoints of a session, with x = x. We write Va to denote the set of variables and covariables; k, k 0 will be used to range over Va . As before, values include booleans and variables. The syntax of processes is as follows: 5
bS ENDc xhvi.P | x[i : m f1 , o : m f2 ] −→A P | x[i : m f1 , o : m f2 · v] bS ELc x / l.P | x[i : m f1 , o : m f2 ] −→A P | x[i : m f1 , o : m f2 · l] bC OMc x[i : m f1 , o : m · m f2 ] | x[i : m f1 , o : m f2 ] −→A x[i : m f1 , o : m f2 ] | x[i : m f1 · m, o : m f2 ] v bR ECVc x(y).P | x[i : v · m f1 , o : m f2 ] −→A P { /y} | x[i : m f1 , o : m f2 ] bB RAc x . {li : Pi }i∈I | x[i : lj · m f1 , o : m f2 ] −→A Pj | x[i : m f1 , o : m f2 ] bI F Tc tt? (P ) : (Q) −→A P
(j ∈ I)
bI F Fc ff? (P ) : (Q) −→A Q
Fig. 2. Reduction relation for aπ processes (contextual congruence rules omitted).
Definition 3 (aπ and aπ ? ). The set aπ of asynchronous session processes is defined as: P, Q ::= khvi.P | k(y).P | k / l.P | k . {li : Pi }i∈I | v? (P ) : (Q) | P | Q | 0 | (νx)P | µX.P | X | k[i : m; e o : m] e We write aπ ? to denote the sub-language of aπ without queues. Differences with respect to Def. 1 appear in the second line of the above grammar. The usual (single) restriction (νx)P is convenient in a queue-based setting; it binds both x and x in P . We consider recursion µX.P rather than input-guarded replication. Communication in aπ is mediated by queues of messages m (values v or labels l), one for each endpoint k; these queues, denoted k[i : m; e o : m], e have output and input parts. Synchronization proceeds as follows: the sending endpoint first enqueues the message m in its own output queue; then, m is moved to the input queue of the receiving endpoint; finally, the receiving endpoint retrieves m from its input queue. We will use to denote the empty queue. Notions of free/bound (recursive) variables are as expected. The operational semantics of aπ is defined as a reduction relation coupled with a structural congruence relation ≡A . The former is defined by the rules in Fig. 2, which either follow the above intuitions for queue-based message passing or are exactly as for π; the latter is defined as the smallest congruence on processes that considers standard principles for parallel composition and inaction, together with the axioms: (νx)(νy)P ≡A (νy)(νx)P (νx)0 ≡A 0 µX.P ≡A P {µX.P/X } k[i : ; o : ] ≡A 0 (νx)P | Q ≡A (νx)(P | Q) if x 6∈ fv(Q). The notion of contexts for aπ includes unary contexts E and binary contexts C: Definition 4 (Contexts for aπ). The syntax of contexts in aπ is given by the following grammar: E ::= [·] | E | P | P | E | (νx)E, where P is an aπ process andQ ‘[·]’ repn resents a ‘hole’. We write C[·1 , ·2 ] to denote binary contexts (ν x e)([·1 ] | [·2 ] | i=1 Pi ) with n ≥ 1. We will write E[P ] (resp. C[P, Q]) to denote the aπ process obtained by filling the hole in E[·] (resp. C[·1 , ·2 ]) with P (resp. P and Q). Both π and aπ abstract from an explicit phase of session initiation in which endpoints are bound together. We thus find it useful to identify aπ processes which are properly initialized (PI): intuitively, processes that contain all queues required to reduce. Definition 5 (Properly Initialized Processes). Let P ≡A (ν x e)(P1 | P2 ) be an aπ process such that P1 is in aπ ? (i.e., it does not include queues) and fv(P1 ) = {k1 , . . . , kn }. We say P is properly initialized (PI) if P2 contains a queue for each session declared in P1 , i.e., if P2 = k1 [i : , o : ] | · · · | kn [i : , o : ]. 6
ReactiveML: A synchronous reactive programming language Based on the reactive model given in [6], ReactiveML [17] is an extension of OCaml that allows unbounded time response from processes, avoiding causality issues present in other SRP approaches. ReactiveML extends OCaml with processes: state machines whose behavior can be executed through several instants. Processes are the reactive counterpart of OCaml functions, which ReactiveML executes instantaneously. In ReactiveML, synchronization is based on signals: events that occur in one instant. Signals can trigger reactions in processes; these reactions can be run instantaneously or in the next instant. Signals carry values and can be emitted from different processes in the same instant. We present the syntax of ReactiveML following [15], together with two semantics, with synchronous and asynchronous communication. We will assume countable infinite sets of variables Vr and names Nr (ranged over by x1 , x2 and n1 , n2 , respectively). Definition 6 (RML). The set RML of ReactiveML expressions is defined as: v, v 0 ::= c | (v, v) | n | λx.e | process e e, e0 ::= x | c | (e, e) | λx.e | e e | rec x = v | match e with {ci → ei }i∈I | let x = e and x = e in e | run e | loop e | signale x : e in e | emit e e | pause | process e | present e? (e) : e | do e when e | do (e) until e(x) → (e) Values v, v 0 , . . . include constants c (booleans and the unit value ()), pairs, names, abstractions, and also processes, which are made of expressions. The syntax of expressions e, e0 extends a standard functional substrate with match and let expressions and with process- and signal-related constructs. Expressions run e and loop e follow the expected intuitions. Expression signalg x : d in e declares a signal x with default value d, bound in e; here g denotes a gathering function that collects the values produced by x in one instant. When d and g are unimportant (e.g., when the signal will only be emitted once), we will write simply signal x in P . We will also write signal x1 , . . . , xn in e when declaring n > 1 distinct signals in e. If expression e1 transitions to the name of a signal then emit e1 e2 emits a signal carrying the value from the instantaneous execution of e2 . Expression pause postpones execution to the next instant. The conditional expression present e1 ? (e2 ) : (e3 ) checks the presence of a signal: if e1 transitions to the name of a signal present in the current instant, then e2 is run in the same instant; otherwise, e3 is run in the next instant. Expression do e when e1 executes e only when e1 transitions to the name of a signal present in the current instant, and suspends its execution otherwise. Expression do (e1 ) until e(x) → (e2 ) executes e1 until e transitions into the name of a signal currently present that carries a value which will substitute x. If this occurs, the execution of e1 stops at the end of the instant and e2 is executed in the next one. Using these basic constructs, we may obtain the useful derived expressions reported in Fig. 3, which include the parallel composition e1 k e2 . We will say that an expression with no parallel composition operator at top level is a thread. We write ≡R to denote the smallest equivalence that satisfies the following axioms: (i) e k () ≡R e; (ii) e1 k e2 ≡R e2 k e1 ; (iii) (e1 k e2 ) k e3 ≡R e1 k (e2 k e3 ). A Synchronous Semantics for RML. Following [15], we define a big-step operational semantics for RML. We require some auxiliary definitions for signal environments and events. Below, ] and v denote usual multiset union and inclusion, respectively. 7
M
M
e1 ; e2 = let _ = () and _ = e1 in e2 e1 k e2 = let _ = e1 and _ = e2 in () M await e1 (x) in e2 = do (loop pause ) until e1 (x) → (e2 ) M let rec process f x1 . . .xn = e1 in e2 = let f = (rec f = λx1 . . .xn .process e1 ) in e2 (n ≥ 1) M if e1 then e2 else e3 = match e1 with {tt → e2 | ff → e3 } Fig. 3. Derived RML expressions.
Definition 7 (Signal Environment). Let D, G, M be sets of default values, gathering functions, and multisets, respectively. A signal environment is a function S : Nr → M (D × G × M), denoted S = [(d1 , g1 , m1 )/n1 , . . . , (dk , gk , mk )/nk ], with k ≥ 1. We use the following notations: S d (ni ) = di , S g (ni ) = gi , and S m (ni ) = mi . Also, S v = fold gi mi di where fold recursively gathers multiple emissions of different values in the same signal; see [17,15] for details. An event E associates a signal ni to a multiset mi that represents the values emitted during an instant: M
Definition 8 (Events). An event is defined as a function E : Nr → M, i.e., E = [m1 /n1 , . . . , mk /nk ], with k ≥ 1. Given events E1 and E2 , we say that E1 is included in E2 (written E1 vE E2 ) if and only if ∀n ∈ Dom(E1 ) ∪ Dom(E2 ) ⇒ E1 (n) v E2 (n). The union E1 and E2 (written E1 tE E2 ) is defined for all n ∈ Dom(E1 ) ∪ Dom(E2 ) as (E1 tE E2 )(n) = E1 (n) ] E2 (n). We now define the semantics of RML expressions. A big-step transition in RML capE,b
tures reactions within a single instant, and is of the form e −−→ e0 where S stands for S
the smallest signal environment (wrt vE and S m ) containing input, output, and local signals; E is the event made of signals emitted during the reaction; b ∈ {tt, ff} is a boolean value that indicates termination: b is false if e is stuck during that instant and is true otherwise. At each instant i, the program reads an input Ii and produces an output Oi . The reaction of an expression obeys four conditions: (C1) (Ii tE Ei ) vE Sim (i.e., S must contain the inputs and emitted signals); (C2) Oi vE Ei (i.e., the output g d signals are included in the emitted signals); (C3) Sid ⊆ Si+1 ; and (C4) Sig ⊆ Si+1 (i.e., default values and gathering functions are preserved throughout instants). Fig. 4 gives selected transition rules; see [7] for a full account. Rules bL-PARc and bL-D ONEc handle let expressions, distinguishing when (a) at least one of the parallel branches has not yet terminated, and (b) both branches have terminated and their resulting values can be used. Rule bRUNc ensures that declared processes can only be executed while they are preceded by run . Rules bL P -S TUc and bL P -U Nc handle loop expressions: the former decrees that a loop will stop executing when the termination boolean of its body becomes ff; the latter executes a loop until Rule bL P -S TUc is applied. Rule bS IG -D ECc declares a signal by instantiating it with a fresh name in the continuation; its default value and gathering function must be instantaneous expressions. Rule bE MITc governs signal emission. Rule bPAUSEc suspends the process for an instant. Rules bS IG -Pc and bS IG -NPc check for presence of a signal n: when n is currently present, the body e2 is run in the same instant; otherwise, e3 is executed in the next instant. Rules bDU-E NDc, bDU-Pc, and bDU-NPc handle expressions do (e1 ) until e2 (x) → (e3 ). Rule bDU-E NDc says that if e1 terminates instanta8
E ,b
E ,b
1 1 e1 − −− − → e01
2 2 e2 − −− − → e02
S
bL-PARc
b1 ∧ b2 = ff
S E1 tE E2 ,ff
let x1 = e1 and x2 = e2 in e3 −−−−−−−→ let x1 = e01 and x2 = e02 in e3 S
E2 ,tt
E1 ,tt
S
S
bL-D ONEc
E ,b
e3 {v1 , v2/x1 , x2 } −−3−→ e03
e2 −−−→ v2
e1 −−−→ v1
S
E1 tE E2 tE E3 ,b
let x1 = e1 and x2 = e2 in e3 −−−−−−−−−−→ e03 S
bRUNc
bL P -U Nc
bL P -S TUc E ,b
E ,tt
E,ff
e0 −−2−→ e00
e −−1−→ process e0
E1 tE E2 ,b
run e −−−−−−→ e
S E,ff
00
e1 −−−→ v1 S
bS IG -D ECc
S
E3 ,b
e3 {n/x} −−−→
e2 −−−→ v2 S
S
E1 tE E2 ,b
0
loop e −−−−−−→ e0
S
E2 ,tt
E ,b
loop e −−2−→ e0
e −−1−→ v
loop e −−−→ e ; loop e
S
E1 ,tt
E ,tt
e −−−→ e0
S
S
S
e03
n fresh S(n) = (v1 , v2 , m)
S E1 tE E2 tE E3 ,b
signale2 x : e1 in e3 −−−−−−−−−−→ e03 S
E ,tt
E ,tt
e1 −−1−→ n
e2 −−2−→ v
S
bE MITc
S
bPAUSEc
E1 tE E2 tE [{v}/n],tt
emit e1 e2 −−−−−−−−−−−−−→ () E1 ,tt
e1 −−−→ n S
bS IG -Pc
E2 ,b
n∈S
e2 −−−→ S E,ff
S
E,tt
e02
e1 −−−→ n S
bS IG -NPc
present e1 ? (e2 ) : (e3 ) −−−→ e02
n 6∈ S E,ff
present e1 ? (e2 ) : (e3 ) −−−→ e3
S
bDU-E NDc
∅,ff
pause −−→ ()
S
S
bDU-Pc
E ,tt
e2 −−2−→ n S
E ,tt
E ,tt
e1 −−1−→ v
e2 −−2−→ n
S E1 tE E2 ,tt
n∈S
S
E ,ff
e1 −−1−→ e01
S E1 tE E2 ,ff
v do (e1 ) until e2 (x) → (e3 ) −−−−−−−→ v do (e1 ) until e2 (x) → (e3 ) −−−−−−−→ e3 {S (n)/x} S
S
E2 ,tt
e2 −−−→ n bDU-NPc
n 6∈ S
S
E1 ,ff
e1 −−−→ S
e01
E1 t E2 ,ff
do (e1 ) until e2 (x) → (e3 ) −−−−E−−−→ do (e01 ) until e2 (x) → (e3 ) S
Fig. 4. Big-step semantics for RML expressions (selection).
neously, then the whole expression terminates. Rule bDU-Pc says that if e2 transitions to a currently present signal n, then e3 is executed in the next instant, substituting x with the values gathered in n. Rule bDU-NPc executes e1 as long as e2 does not reduce to a currently present signal. We shall rely on a simple notion of equality: Definition 9 (Equality with case normalization). Let ,→R denote the extension of ≡R with the axiom match cj with {ci → Pi }i∈I ,→R Pj , where cj is a constant and j ∈ I. RMLq: ReactiveML with a Queue-based Semantics. We extend RML with an explicit store of queues that keeps the state of the executed program. Unlike signals, the store of queues is preserved throughout time. The syntax of RML is extended with constructs that modify the queues located in the store; the resulting language is called RMLq: Definition 10 (RMLq). RMLq expressions are obtained by extending the grammar of values in Def. 6 with the following forms: v ::= · · · | pop | put | isEmpty. 9
bP UT-Qc
bP OP -Qc ∅,tt
∅,tt
hput q v ; Σ, q : e hi 9999K h() ; Σ, q : e h · vi hpop q ; Σ, q : v · e hi 9999K hv ; Σ, q : e hi S
S
bNE MPTYc
bP OP -Q c
∅,tt ∅,ff hisEmpty q ; Σ, q : e hi 9999K h() ; Σ, q : e hi hpop q ; Σ, q : i 9999K hpop q ; Σ, q : i S
S
∅,ff
bE MPTYc hisEmpty q ; Σ, q : i 9999K hisEmpty q ; Σ, q : i S
Fig. 5. Big-step semantics for RMLq: Queue-related operations.
The new constructs allow RMLq programs to modify queues, which are ranged over by q, q 0 , . . .. Construct put receives a queue and an element as parameters and pushes the element into the end of the queue. Construct pop takes a queue and dequeues its first element; if the queue is empty in the current instant the process will block the current thread until an element is obtained. Construct isEmpty blocks a thread until the instant in which a queue stops being empty. The semantics of RMLq includes a state Σ, Σ 0 ::= ∅ | Σ, q : ve (i.e., a possibly empty collection of queues) and configurations K, K 0 ::= he ; Σi. The big-step E,b
semantics then has transitions of the form he ; Σi 999K he0 ; Σ 0 i, where S is a signal S
environment, b is a termination boolean, and E is an event. The corresponding transition system is generated by rules including those in Fig. 5 (see also [7]). Most transition rules for RMLq are interpreted as for RML; we briefly discuss queue-related rules in Fig. 5. Rule bP UT-Qc pushes an element into a queue and terminates instantaneously. Rule bP OP -Qc takes the first element from the queue (if not empty) and terminates instantaneously. Rule bNE MPTYc enables isEmpty to terminate instantaneously if the queue is not empty. Rule bP OP -Q c keeps the thread execution stuck for at least one instant if the queue is empty; Rule bE MPTYc is similar. We rule out programs with parallel pop/put operations along the same session in the same instant.
4
Expressiveness Results
We present our main results: correct translations of π into RML and of aπ into RMLq. The Formal Notion of Encoding We define notions of language, translation, and encoding by adapting those from Gorla’s framework for relative expressiveness [10]. Definition 11 (Languages & Translations). A language L is a tuple hP, − →, ≈i, where P is a set of processes, − → denotes an operational semantics, and ≈ is a behavioral equality on P. A translation from Ls = hPs , − →s , ≈s i into Lt = hPt , − →t , ≈t i (each with countably infinite sets of variables Vs and Vt , respectively) is a pair hJ·K, ψJ·K i, where J·K : Ps → Pt is a mapping, and ψJ·K : Vs → Vt is a renaming policy for J·K. We are interested in encodings: translations that satisfy certain correctness criteria:
Definition 12 (Encoding). Let Ls = hPs , − →s , ≈s i and Lt = hPt , − →t , ≈t i be languages; also let hJ·K, ψJ·K i be a translation between them (cf. Def. 11). We say that such a translation is an encoding if it satisfies the following criteria: 10
1. Name invariance: For all S ∈ Ps and substitution σ, there exists σ 0 such that JSσK = JSKσ 0 , with ψJ·K (σ(x)) = σ 0 (ψJ·K (x)), for any x ∈ Vs . 2. Compositionality: Let ress (·, ·) and pars (·, ·) (resp. rest (·, ·) and part (·, ·)) denote restriction and parallel composition operators in Ps (resp. Pt ). Then, we define: Jress (e x, P )K = rest (ψJ·K (e x), JP K) and Jpars (P, Q)K = part (JP K, JQK). 3. Operational correspondence, i.e., it is sound and complete: (1) Soundness: For all S ∈ Ps , if S − →s S 0 , there exists T ∈ Pt such that JSK =⇒t T and T ≈t JS 0 K. (2) Completeness: For all S ∈ Ps and T ∈ Pt , if JSK =⇒t T , there exists S 0 such that S =⇒s S 0 and T ≈t JS 0 K. While name invariance and compositionality are static correctness criteria, operational correspondence is a dynamic correctness criterion. Notice that our notion of compositionality is less general than that in [10]: this is due to the several important differences in the structure of the languages under comparison (π vs. RML and aπ vs. RMLq). We shall present translations of π into RML and of aπ into RMLq, which we will show to be encodings. We instantiate Def. 11 with the following languages: Definition 13 (Concrete Languages). We shall consider: - Lπ will denote the tuple hπ, −→, ≡S i, where π is as in Def. 1; −→ is the reduction semantics in Fig. 1; and ≡S is the structural congruence relation for π. E,b
E,b
S
S
- LRML will denote the tuple hRML, −−→, ,→R i, where RML is as in Def. 6; −−→ is the big-step semantics for RML; and ,→R is the equivalence in Def. 9. - Laπ will denote the tuple haπ, −→A , ≡A i, where aπ is as in Def. 3; −→A is the reduction semantics in Fig. 2; and ≡A is the structural congruence relation for aπ. E,b
E,b
S
S
- LRMLq will denote the tuple hRMLq, 999K, ≡R i, where RMLq is as in Def. 10; 999K is the big-step semantics for RMLq; and ≡R is the equivalence for RML. When events, termination booleans, and signal environments are unimportant, we write E,b
E,b
S
S
P 7−→ Q instead of P −−→ Q, and K 7999K K 0 instead of K 999K K 0 . Encoding Lπ into LRML Key aspects in our translation of Lπ into LRML are: (i) the use of value carrying signals to model communication channels; and (ii) the use of a continuation-passing style (following [8]) to model variables in π using RML signals. Definition 14 (Translating Lπ into LRML ). Let hJ·Kf , ψJ·Kf i be a translation where: (1) ψJ·Kf (x) = x, i.e., every variable in π is mapped to the same variable in RML. (2) J·Kf : Lπ → LRML is as in Fig. 6, where f is a substitution function. Function f in J·Kf ensures that fresh signal identifiers are used in each protocol action. The translation of xhvi.P declares a new signal x0 which will be sent paired with value v through signal x; process JP Kf,{x←x0 } is executed in the next instant. Dually, the translation of x(y).P awaits a signal carrying a pair, composed of a value and the signal name that to be used in the continuation, which is executed in the next instant. Translations for selection and branching are special cases of those for output and input. Restriction (νxy)P is translated by declaring a fresh signal w, which replaces 11
M
signal x0 in (emit fx (v, x0 ); pause ; JP Kf,{x←x0 } ) await fx (y, w) in JP Kf,{x←w} signal x0 in (emit fx (l, x0 ); pause ; JP Kf,{x←x0 } ) await fx (l, w) in match l with {li → JPi Kf,{x←w} } if v then (pause ; P ) else (pause ; Q) signal w in JP Kf,{x←w,y←w} let rec process repl α β = signal x0 in do (loop present fα ? (emit x0 ; pause ) : (())) until fα (y, w) → (run β{α←w} ) k await x0 in run (repl α β) in run repl x (process JP Kf ) M M JP | QKf = JP Kf k JQKf J0Kf = ()
Jxhvi.P Kf Jx(y).P Kf Jx / l.P Kf Jx . lj {li : Pi }i∈I Kf Jv? (P ) : (Q)Kf J(νxy)P Kf J∗ x(y).P Kf
= M = M = M = M = M = M =
Fig. 6. Translation from Lπ to LRML (Def. 14). Notice that fx is a shorthand for f (x).
x, y in JP Kf . Conditionals, parallel composition and inaction are translated homomorphically. Input-guarded replication is a special case of recursion, enabling at most one copy of the spawned process in the same instant; such a copy will be blocked until the process that spawned it interacts with some process. In Fig. 6, α, β denote variables inside the declaration of a recursive process, distinct from any other variables. We state our first technical result: the translation of Lπ into LRML is an encoding. In the proof, we identify a class of well-formed π processes that have at most one output and selection per endpoint in the same instant; see [7] for details. Theorem 1. Translation hJ·Kf , ψJ·Kf i is an encoding, in the sense of Def. 12. Encoding Laπ into LRMLq The main intuition in translating aπ into RMLq is to use the queues of RMLq coupled with a handler process that implements the output-input transmission between queues. We start by introducing some auxiliary notions. Q Q Notation 1 Let P ≡A (ν x e)( i∈{1,...,n} Qi | kj ∈ek kj [i : , o : ] be PI (cf. Def. 5) with variables e k. We will write P as Cl [Ql , K(e k)], where l ∈ {1, . . . , n}, Cl [·1 , ·2 ] = Q Q e Qj | [·1 ] | [·2 ], and K(k) = e kj [i : , o : ]. j∈{1,...,n}\{l}
k j ∈k
This notation allows us to distinguish two parts in a PI process: the non-queue processes and the queue processes K(e k). We now define the key notion of handler process: Definition 15Q(Handler process). Given e k = {k1 , . . . , kn }, the handler process H(e k) is defined as i∈{1,...,n} I(ki ) k O(ki ), where I(k) and O(k) are as in Fig. 7. Given an endpoint k, a handler defines parallel processes I k and Ok to handle input and output queues. Transmission is a handshake where both Ok and I k (or viceversa) must be ready to communicate. If ready, Ok sends a pair containing the message (pop ko ) and a fresh signal for further actions (α0 ). Once the pair is received, it is enqueued in k i (i.e., the dual I k ). The process is recursively called in the next instant with the new endpoints. The translation of aπ ? into RMLq requires a final auxiliary definition: 12
M
I(k) = let rec process I α = (present ackα ? (emit ackα ; await α(x, α0 ) in (put x ki ); run I α0 ) : (I α) in run I k M O(k) = let rec process O α = signal α0 in isEmpty αo ; emit ackα ; (present ackα ? (emit α ((pop ko ), α0 ); pause ; run O α0 ) : (run O α) in run O k Fig. 7. Components of handler processes (Def. 15) M
{[x(y).P ]} = let y = pop xi in {[P ]} M {[x . {li : Pi }i∈I ]} = let y = pop xi in match l with {li : {[Pi ]}}i∈I M {[b? (P ) : (Q)]} = if b then {[P ]} else {[Q]} M {[µX.P ]} = let rec process αX = {[P ]} in run αX
{[xhvi.P ]} {[x / l.P ]} {[P | Q]} {[(νx)P ]} {[X]} {[0]}
M
= M = M = M = M = M =
put xo v; {[P ]} put xo l; {[P ]} {[P ]} k {[Q]} signal x, x in {[P ]} pause ; run αX ()
Fig. 8. Auxiliary translation from aπ ? into RMLq (Def. 17).
Definition 16. We define δ(·) as a function that maps aπ processes into RMLq states: δ(k[i : e h; o : m]) e = {ki : e h, ko : m} e δ(P | Q) = δ(P ) ∪ δ(Q) δ((νx)P ) = δ(P ) and as δ(P ) = ∅ for every other aπ process. Definition 17 (Translating Laπ into LRMLq ). Let h([·]), ψ([·]) i be a translation where: - ψ([·]) (k) = k, i.e., every variable in aπ is mapped to the same variable in RMLq. - ([·]) : Laπ → LRMLq is defined for properly initialized aπ processes C[Q, K(e k)], which are translated into RMLq configurations as follows: ([C[Q, K(e k)]]) = h{[C[Q, 0]]} k H(e k) ; δ(K(e k))i where {[·]} : Laπ? → LRMLq is in Fig. 8; H(e k) is in Def. 15; and δ(·) is in Def. 16. Two key ideas in translation ([·]) are: queues local to processes and compositional (queue) handlers. Indeed, communication between an endpoint k and its queues ki , ko proceeds instantaneously, for such queues should be local to the process implementing session k. Queue handlers effectively separate processes/behavior from data/state. As such, it is conceivable to have handlers that have more functionalities than those of H(e k). In [7] we provide an example of a handler more sophisticated than H(e k). Translation ([·]) is in two parts. First, {[·]} translates non-queue processes: output and input are translated into queuing and dequeuing operations, respectively. Selection and branching are modeled similarly. Translations for the conditional, inaction, parallel, and recursion is as expected. Recursion is limited to a pause-guarded tail recursion in {[·]} to avoid loops of instantaneous expressions and nondeterminism when accessing queues. Second, ([·]) creates an RML configuration by composing the RMLq process obtained via {[·]} with appropriate handlers and with the state obtained from the information in aπ 13
queues. Because of this two-part structure, static correctness properties are established for {[·]} (for this is the actual translation of source processes), whereas operational correspondence is established for ([·]) (which generates an RMLq configuration). Theorem 2 (Name invariance and compositionality for {[·]}). Let P , σ, x, and E[·] be an aπ ? process, a substitution, a variable in aπ ? , and an evaluation context (cf. Def. 4), respectively. Then: (1) {[P σ]} = {[P ]}σ, and (2) {[E[P ]]} = {[E]} {[P ]} . Theorem 3 (Operational correspondence for ([·])). Given a properly initialized aπ process C[Q, K(e k)], it holds that: 1. Soundness: If C[Q, K(e k)] −→A C[Q0 , K0 (e k)] then ([C[Q, K(e k)]]) 7999K ([C 0 [Q00 , K00 (e k)]]), for some Q00 , K00 (e x), C 0 where 0 0 ∗ 0 00 00 C[Q, K(e x)] −→A C[Q , K (e x)] −→A (ν x e)C [Q , K (e x)]. 2. Completeness: If ([C[Q, K(e x)]]) 7999K R then there exist Q0 ,C 0 ,K0 (e x) such that 0 0 ∗ e)C [Q , K0 (e x)] and R = ([C 0 [Q0 , K0 (e x)]]). C[Q, K(e x)] −→A (ν x In soundness, a single RMLq step mimicks one or more steps in aπ, i.e., several source computations can be grouped into the same instant. This way, e.g., the interaction of several outputs along the same session with their queue (cf. Rule bS ENDc) will take place in the same instant. In contrast, several queue synchronizations in the same session (cf. Rule bC OMc) will be sliced over different instants. Conversely, completeness ensures that our encoding does not introduce extraneous behaviors: for every RMLq transition of a translated process there exists one or more corresponding aπ reductions.
5
Closing Remarks
We have shown that ReactiveML can correctly encode session-based concurrency, covering both synchronous and asynchronous (queue-based) communications.1 Our encodings are executable: as such, they enable to integrate session-based concurrency in actual RML programs featuring declarative, reactive, timed, and contextual behavior. This is an improvement with respect to previous works, which extend the π-calculus with some (but not all) of these features and/or lack programming support. Interestingly, since ReactiveML has a well-defined semantics, it already offers a firm basis for both foundational and practical studies on session-based concurrency. Indeed, ongoing work concerns the principled extension of our approach to the case of multiparty sessions. We have not considered types in source/target languages, but we do not foresee major obstacles. In fact, we have already shown that our encoding J·Kf supports a large class of well-typed π processes in the system of [19], covering a typed form of operational correspondence (cf. Corollary 3) but also type soundness: if P is a well-typed π process, then JP Kf is a well-typed RML expression—see Thm. 11. We conjecture a similar result for ([·]), under an extension of [19] with queues. On the ReactiveML side, we can exploit the type-and-effect system in [15] to enforce cooperative programs (roughly, 1
Synchronous communication as in the (session) π-calculus should not be confused with the synchronous programming model of ReactiveML.
14
programs without infinite loops). Since J·Kf and ([·]) already produce well-typed, executable ReactiveML expressions, we further conjecture that they are also cooperative, in the sense of [15]. Acknowledgements We thank Ilaria Castellani, Cinzia Di Giusto, and the anonymous reviewers for useful remarks and suggestions. This work has been partially sponsored by CNRS PICS project 07313 (SuCCeSS) and EU COST Actions IC1201 (BETTY), IC1402 (ARVI), and IC1405 (Reversible Computation).
References 1. M. Bartoletti, T. Cimoli, M. Murgia, A. S. Podda, and L. Pompianu. Compliance and subtyping in timed session types. In FORTE, volume 9039 of LNCS, pages 161–177. Springer, 2015. 2. A. Benveniste, P. Caspi, S. A. Edwards, N. Halbwachs, P. L. Guernic, and R. de Simone. The synchronous languages 12 years later. Proceedings of the IEEE, 91(1):64–83, 2003. 3. L. Bocchi, K. Honda, E. Tuosto, and N. Yoshida. A theory of design-by-contract for distributed multiparty interactions. In CONCUR 2010, volume 6269 of LNCS, pages 162–176. Springer - Verlag, 2010. 4. L. Bocchi, W. Yang, and N. Yoshida. Timed multiparty session types. In Proc. of CONCUR’14, volume 8704, pages 419–434. Springer, 2014. 5. E. Bonelli, A. B. Compagnoni, and E. L. Gunter. Correspondence assertions for process synchronization in concurrent communications. J. Funct. Program., 15(2):219–247, 2005. 6. F. Boussinot and R. de Simone. The SL synchronous language. IEEE Trans. Software Eng., 22(4):256–266, 1996. 7. M. Cano, J. Arias, and J. A. Pérez. Session-based Concurrency, Reactively (Extended Version), 2017. Available at http://www.jperez.nl/publications. 8. O. Dardha, E. Giachino, and D. Sangiorgi. Session types revisited. In Proc. of PPDP’12, pages 139–150, 2012. 9. X. Fu, T. Bultan, and J. Su. Conversation protocols: a formalism for specification and verification of reactive electronic services. Theor. Comput. Sci., 328(1-2):19–37, 2004. 10. D. Gorla. Towards a unified approach to encodability and separation results for process calculi. Inf. Comput., 208(9):1031–1053, 2010. 11. N. Halbwachs, F. Lagnier, and C. Ratel. Programming and verifying real-time systems by means of the synchronous data-flow language LUSTRE. IEEE Trans. Software Eng., 18(9):785–793, 1992. 12. K. Honda, V. T. Vasconcelos, and M. Kubo. Language Primitives and Type Discipline for Structured Communication-Based Programming. In Proc. of ESOP’98, volume 1381, pages 122–138. Springer, 1998. 13. H. Hüttel, I. Lanese, V. T. Vasconcelos, L. Caires, M. Carbone, P.-M. Deniélou, D. Mostrous, L. Padovani, A. Ravara, E. Tuosto, H. T. Vieira, and G. Zavattaro. Foundations of session types and behavioural contracts. ACM Comput. Surv., 49(1):3:1–3:36, Apr. 2016. 14. D. Kouzapas, N. Yoshida, R. Hu, and K. Honda. On asynchronous eventful session semantics. Mathematical Structures in Computer Science, 26(2):303–364, 2016. 15. L. Mandel and C. Pasteur. Reactivity of Cooperative Systems - Application to ReactiveML. In 21st International Symposium, SAS 2014, Munich, Germany, 2014., pages 219–236, 2014. 16. L. Mandel, C. Pasteur, and M. Pouzet. ReactiveML, ten years later. In Proc. of PPDP 2015, pages 6–17, 2015.
15
17. L. Mandel and M. Pouzet. ReactiveML: a reactive extension to ML. In Proc. of PPDP’05, pages 82–93. ACM, 2005. 18. R. Milner, J. Parrow, and D. Walker. A calculus of mobile processes, I. Inf. Comput., 100(1):1–40, 1992. 19. V. T. Vasconcelos. Fundamentals of session types. Inf. Comput., 217:52–70, 2012.
16
(Qualifiers) (Pretypes)
(Types)
(Contexts)
q ::=
lin un p ::= ?T.T !T.T ⊕{li : Ti }i∈I &{li : Ti }i∈I T ::= bool end qp a µa.T Γ , ∆ ::= ∅ Γ, x : T
(linear) (unrestricted) (receive) (send) (select) (branching) (boolean) (termination) (qualified pretype) (type variable) (recursive type) (empty context) (assumption)
Fig. 9. Session Types: Qualifiers, Pretypes, Types, Contexts.
A A.1
Appendix for Section 3 Type System for π
Here we present the type system for the language π given in §3 and show an example of typing. Definition 18 (Session Types: Syntax). The syntax of session types is given in Fig. 9. We use q to range over qualifiers, p to range over pretypes, and T to range over types. The type syntax includes pretypes and types. Pretype !T1 .T2 denotes output, and types a channel that sends a value of type T1 and continues according to type T2 . Dually, pretype ?T1 .T2 denotes input, and types a channel that receives a value of type T1 and then proceeds according to type T2 . Pretypes ⊕{li : Ti }i∈I and &{li : Ti }i∈I denote labeled selection (internal choice) and branching (external choice), respectively. Types annotate channels and can be either (1) bool, used for constants and variables, (2) end, which types a channel endpoint that can no longer be used, (3) qualified pretypes, which type the actions executed by a channel, or (4) recursive types for disciplining potentially infinite communication patterns. The approach to recursion taken for π in [19] is equi-recursive; i.e., a recursive type is assumed to be equal to its unfolding. Qualifiers refer to linear or unrestricted behaviors. Intuitively, linearly qualified types are assigned to endpoints occurring in exactly one thread (a process not comprising parallel composition); the unrestricted qualifier allows an endpoint to occur in multiple threads. For each qualifier q, there are predicates q(T ) and q(Γ ) defined as follows: – un(T ) if and only if T = bool or T = end or T = un p. – lin(T ) if and only if true. – q(Γ ) if and only if (x : T ) ∈ Γ implies q(T ). Session type systems depend on type duality to relate session types with complementary (or opposite) behaviors: e.g., the dual of input is output (and vice versa); branching is the dual of selection (and vice versa). For the purposes of this paper, we only provide an inductive definition of duality. For a more detailed study of duality see, e.g., [App4] for a formal definition. We write T to denote the dual of type T . 17
Definition 19 (Duality of session types). For every type T , except bool, we define duality as: end = end
!S.U = ?S.U
?S.U = !S.U
&{li : Si }i∈I = ⊕{li : Si }i∈I
⊕{li : Si }i∈I = &{li : Si }i∈I
a = a µa.S = µa.S
Typing uses a context splitting operator on contexts, denoted ◦, which maintains the linearity invariant for channels. It is defined below. Definition 20 (Context splitting). Let Γ1 and Γ2 be two contexts; we write Γ1 , Γ2 to denote their concatenation. The context splitting of Γ1 and Γ2 , written Γ1 ◦ Γ2 , is defined as follows: Γ = Γ1 ◦ Γ2 un(T ) Γ, x : T = (Γ1 , x : T ) ◦ (Γ2 , x : T ) Γ = Γ1 ◦ Γ2 lin(T ) Γ = Γ1 ◦ Γ2 lin(T ) Γ, x : T = (Γ1 , x : T ) ◦ Γ2 Γ, x : T = Γ1 ◦ (Γ2 , x : T ) ∅◦∅=∅
Given a context Γ and a process P , typing judgments are of the form Γ ` P . Fig. 10 gives the typing rules for π processes; we now give some intuitions (see [19] for full details). Rules (T:B OOL) and (T:VAR) are for variables; in both cases, we check that all linear variables are consumed, using predicate un(·). Rule (T:N IL) types the inactive process 0; it also checks that the context only contains unrestricted variables. Rule (T:I F) type-checks the conditional process. Rule (T:R EPL) checks replicated processes, making sure that the associated context is unrestricted. Rule (T:PAR) types parallel composition using context splitting to divide resources among the two sub-processes. Rule (T:R ES) types the restriction operator: it performs a duality check on the types of the co-variables. Rule (T:I N) types an input process: it checks whether x has the right type and checks the continuation; it also adds variable y with type T and x with the type of the continuation to the context. To type-check a process xhvi.P , Rule (T:O UT) splits the context in three parts: the first is used to check the type of the sent object v; the second is used to check the type of subject x; the third is used to check the continuation P . Rules (T:B RA) and (T:S EL) type-check label branching and label selection processes, and they in a fashion similar to (T:I N) and (T:O UT), respectively. We state the subject reduction property for this type system: Theorem 4 ([19]). If Γ ` P and P −→ Q then Γ ` Q. We now collect some results that concern the structure of processes; they all follow [19]. Some auxiliary notions are needed. Notation 2 ((Typable) Programs) A process P such that fn(P ) = ∅ is called a program. Therefore, program P is typable if it is well-typed under the empty environment ( ` P ). Example 1. The π process xhv1 i.0 | xhv2 i.0 | y(z).0
(1)
can be well-typed in the above system under the context Γ = {x : µa.un!bool.a, y : lin?bool.end}. For the sake of presentation assume Γ 0 = {x : µa.un!bool.a}. The derivation tree is as follows: D1
D2
.. .. . . (T:O UT ) 0 (T:O UT ) 0 Γ ` xhv1 i.0 Γ ` xhv2 i.0 (T:PAR ) Γ 0 ` xhv1 i.0 | xhv2 i.0 (T:PAR ) Γ ` xhv1 i.0 | xhv2 i.0 | y(z).0 18
D3
.. . (T:I N ) Γ ` y(z).0
(T:B OOL )
un(Γ ) Γ ` ff, tt : bool
(T:I F )
Γ1 ` v : bool
(T:VAR )
Γ2 ` P
un(Γ1 , Γ2 ) Γ1 , x : T, Γ2 ` x : T
Γ2 ` Q
Γ1 ◦ Γ2 ` v? (P ) : (Q) (T:PAR )
Γ1 ` P
(T:I N ) (T:O UT ) (T:S EL ) (T:B RA )
Γ2 ` Q
Γ1 ◦ Γ2 ` P | Q Γ1 ` x : q ?T.U
(T:N IL )
(T:R EPL )
(T:R ES )
Γ `P
un(Γ ) Γ `0
un(Γ )
Γ ` ∗P
Γ, x : T, y : T ` P Γ ` (νxy)P
(Γ2 , y : T ) ◦ x : U ` P
Γ1 ◦ Γ2 ` x(y).P
Γ1 ` x : q !T.U
Γ2 ` v : T
Γ3 ◦ x : U ` P
Γ1 ◦ Γ2 ◦ Γ3 ` xhvi.P
Γ1 ` x : q ⊕ {li : Ti }i∈I
Γ2 ◦ x : Tj ` P
j∈I
Γ1 ◦ Γ2 ` x / lj .P Γ1 ` x : q & {li : Ti }i∈I
∀i ∈ I. Γ2 ◦ x : Ti ` Pi
Γ1 ◦ Γ2 ` x . {li : Pi }i∈I
Fig. 10. Session types: Typing rules for π processes.
where D1 ,D2 , and D3 represent corresponding branches of the previous derivation tree, which have been left out for the sake of presentation. We write D1 to represent the following derivation: (T:VAR ) (T:O UT )
un(Γ 0 ) un(Γ 0 ) (T:B OOL ) Γ 0 ` x : un!bool.a{S/a} Γ 0 ` v1 : bool Γ 0 ` xhv1 i.0
(T:N IL )
un(Γ 0 ) Γ0 ` 0
where S = µa.un!bool.a. Note that the leftmost premise of the rule: Γ 0 ` x : un!bool.T {S/a} can conclude thanks to the equi-recursive treatment of recursive types in [19]. This means that a type µa.T is equivalent to its unfolding. Derivation D2 is represented by the following tree: (T:VAR ) (T:O UT )
un(Γ 0 ) un(Γ 0 ) (T:B OOL ) Γ 0 ` x : un!bool.a{S/a} Γ 0 ` v2 : bool Γ 0 ` xhv2 i.0
(T:N IL )
un(Γ 0 ) Γ0 ` 0
Lastly, D3 represents the following derivation: (T:VAR ) (T:I N )
un(Γ 0 ) Γ 0 , y : lin?bool.end ` y : lin?bool.end Γ ` y(z).0
(T:N IL )
un(Γ 0 ) Γ 0 , z : bool, y : U ` 0
Notice that processes may be typed under different environments. For example, the process in (1) could be typed under environment Γ 00 = {x : µa.un!bool.a, y : µa.un?bool.a}, with a derivation tree similar to the one above. Notice that µa.un!bool.a and µa.un?bool.a are dual types. 19
bR ECURc E,tt v{rec x = v/x} −−−→ v 0
bPAIRc bVALc
E2 ,tt
E1 ,tt
e2 −−−→ v2
e1 −−−→ v1
S
S
S
E1 tE E2 ,tt
∅,tt
E,tt
rec x = v −−−→ v 0
(e1 , e2 ) −−−−−−−→ (v1 , v2 )
v −−→ v
S
S
S
E2 ,tt
E1 ,tt
e2 −−−→ v
e3 { S E1 tE E2 tE E3 ,tt
e1 −−−→ λx.e3 S
bA PPLc
0
0
E3 ,tt
v /x} −−−→ v S
e1 e2 −−−−−−−−−−→ v S
E1 ,tt
e −−−→ cj bC ASEc
E ,b
ej −−2−→ e0j
j∈I
S
S E1 tE E2 ,b
match e with {ci → ei }i∈I −−−−−−→ e0j S
E1 ,b1
−−− → e1 − bL-PARc
S
E2 ,b2
e01
−−− → e2 −
e02
b1 ∧ b2 = ff
S E1 tE E2 ,ff
let x1 = e1 and x2 = e2 in e3 −−−−−−−→ let x1 = e01 and x2 = e02 in e3 S
E1 ,tt
E2 ,tt
e1 −−−→ v1
e2 −−−→ v2
S
bL-D ONEc
S
E ,b
e3 {v1 , v2/x1 , x2 } −−3−→ e03 S
E1 t E2 t E3 ,b
E let x1 = e1 and x2 = e2 in e3 −−−−E−−−− −−→ e03
S
bRUNc
bL P -U Nc
bL P -S TUc
E ,tt
e −−1−→ process e0 S
E ,b S
E1 t E2 ,b
e1 −−−→ v1 S
bS IG -D ECc
S
E loop e −−−− −−→ e0
S
E2 ,tt
S
E ,b e3 {n/x} −−3−→ e03
e2 −−−→ v2 S
S
E1 t E2 ,b
loop e −−−→ e0 ; loop e
S
E ,b
loop e −−2−→ e0
e −−1−→ v
S E,ff
E run e −−−− −−→ e00
E1 ,tt
E ,tt
E,ff
e −−−→ e0
e0 −−2−→ e00
n fresh S(n) = (v1 , v2 , m)
S E1 tE E2 tE E3 ,b
signale2 x : e1 in e3 −−−−−−−−−−→ e03 S
E1 ,tt
e1 −−−→ n S
bE MITc
E2 ,tt
e2 −−−→ v S
E1 tE E2 tE [{v}/n],tt
bPAUSEc
emit e1 e2 −−−−−−−−−−−−−→ () S
E1 ,tt
e1 −−−→ n bS IG -Pc
S
n∈S
E2 ,b
e2 −−−→ S E,ff
∅,ff
pause −−→ () S
E,tt
e02
e1 −−−→ n bS IG -NPc
present e1 ? (e2 ) : (e3 ) −−−→ e02
S
n 6∈ S E,ff
present e1 ? (e2 ) : (e3 ) −−−→ e3
S
S
Fig. 11. Big-step semantics for RML expressions (Part 1).
A.2
Full transition rules for RML
Fig. 11 and Fig. 12 show a full account of all the transitions rules in RML. They are explained as follows: – Rule bVALc indicates that values can be kept during subsequent instants, however their execution always terminates (i.e., they do not suspend the thread). – Rule bPAIRc shows that the internal elements of each pair should be instantaneous. – Rule bR ECURc refers to a single unfolding of a recursive function, which must be done instantaneously. – Rule bA PPLc is the usual rule for application on functions, the involved expressions should terminate instantaneously. – Rule bC ASEc is the usual ML match operator. We set that the matched expression must be resolved instantaneously. 20
bDW-NSc
bDW-I NTc E,tt
e2 −−−→ n
E ,tt
e2 −−2−→ n
n 6∈ S
S
E ,ff
e1 −−1−→ e01
n∈S
S
S
E1 tE E2 ,ff
E,ff
do e1 when e2 −−−→ do e1 when n
do e1 when e2 −−−−−−−→ do e01 when n
bDW-E NDc
bDU-E NDc
S
E ,tt
e2 −−2−→ n S
n∈S
S
E ,tt
E ,tt
e1 −−1−→ v
S E1 tE E2 ,tt
e2 −−2−→ n S
S
E1 t E2 ,tt
do (e1 ) until e2 (x) → (e3 ) −−−−E−−−→ v
do e1 when e2 −−−−−−−→ v S
S
E2 ,tt
e2 −−−→ n bDU-Pc
E ,tt
e1 −−1−→ v
n∈S
S
E1 ,ff
e1 −−−→ S
e01
v E1 t E2 ,ff do (e1 ) until e2 (x) → (e3 ) −−−−E−−−→ e3 {S (n)/x} S
E2 ,tt
e2 −−−→ n bDU-NPc
n 6∈ S
S
E ,ff
e1 −−1−→ e01 S
E1 tE E2 ,ff
do (e1 ) until e2 (x) → (e3 ) −−−−−−−→ do (e01 ) until e2 (x) → (e3 ) S
Fig. 12. Big-step semantics for RML expressions (Part 2).
– Rules bL-PARc and bL-D ONEc handle let expressions, distinguishing the cases in which (a) at least one of the parallel branches has not yet terminated, and (b) both branches have terminated and their resulting values can be used in the body of the let. – Rule bRUNc indicates that declared processes can only be executed while preceded by a run operator. – Rules bL P -S TUc and bL P -U Nc handle loop expressions: the former decrees that a loop will stop executing when the termination boolean of its body becomes ff; the latter executes a loop until Rule bL P -S TUc is applied. If the body of the loop is instantaneous, then the execution would require an infinite tree, which would lead to cooperativity [15]. This is why expressions where the body is instantaneous (e.g., loop ()) have no semantics. – Rule bS IG -D ECc declares a signal by instantiating it with a fresh name in the continuation; its default value and the gathering function must be instantaneous expressions. – Rule bE MITc governs signal emission. – Rule bPAUSEc suspends the thread for a single instant. – Rules bS IG -Pc and bS IG -NPc check for presence of a signal: when the signal is currently present the body e2 is executed in the same instant; otherwise, e3 is executed in the next instant. – Rules bDW-NSc, bDW-I NTc, and bDW-E NDc govern expressions do e1 when e2 . Rule bDW-NSc suspends the execution of e1 when e2 transitions to a signal not currently present. Rule bDW-I NTc decrees that when e2 transitions to a currently present signal e1 is executed as long as the signal is present. Rule bDW-E NDc says that if e2 transitions to a currently present signal and e1 terminates instantaneously, then the whole expression terminates. – Rules bDU-E NDc, bDU-Pc, and bDU-NPc handle expressions do (e1 ) until e2 (x) → (e3 ). Rule bDU-E NDc says that if e1 terminates instantaneously, then the whole expression terminates. Rule bDU-Pc says that if e2 transitions to a currently present signal (n), then e3 is executed in the next instant, substituting x with the values gathered in n. Rule bDU-NPc executes e1 as long as e2 does not reduce to a currently present signal. 21
A.3
Behaviors and reactivity for RML
Following [15], we present a type-and-effect system for RML. First, we define behaviors, a simple language to completely abstract values and the presence on signals. Behaviors will be used to analyze the reactivity, understood as the absence of infinite instantaneous loops. In [15] they decided to to keep an abstraction of the structure of the process, so as to have reasonable precision. The behaviors Assume a set K of behaviors that range over κ, κ1 , . . . , behavior variables range over φ, φ1 , . . . . Free variables are defined as usual, represented by a set fbv(·). Definition 21 (Behaviors). The set π of session processes is defined as: κ, κ1 , . . . ::= • | 0 | φ | κ2 k κ1 | κ1 ; κ2 | κ1 + κ2 | µφ.κ | run κ Non-instantaneous actions (i.e., actions that take more than one instant to execute) are represented by •, instantaneous ones are represented with 0. The language of behaviors also include variables (φ), since we need to represent processes that take processes as parameters, considering that RML allows higherorder definitions. Behaviors must represent the structure of the process; therefore, we start by having a parallel composition operator on behaviors: κ1 k κ2 . Observe that two RML processes in parallel are noninstantaneous, only if each of the processes is non-instantaneous. The same logic is applied to the sequential operator and recursive operators, as an example consider the following processes: let rec process goodRec = pause ; run goodRec let rec process badRec = run badRec; pause Notice that goodRec will be non-instantaneous as the instants are clearly marked by the pause operator, whereas badRec will be an instantaneous loop, as the recursive call comes before the pause operator. The behavior κ1 +κ2 allow us to represents choice, for example, and conditional operator. The recursion behavior µφ.κ allow us to model recursive behavior and they are defined as usual: µφ.κ = κ{µφ.κ/φ}
µφ.κ = κ if φ 6∈ fbv(κ)
Notice that there is no operator for representing the behavior of a loop. Indeed, loops are just a special case of recursion, hence, we will define κ∞ = µφ.κ; run φ to be the behavior of a loop. Reactive behaviors In this section we will define the notion of reactivity for behaviors. We start by defining non-instantaneous behavior: Definition 22 (Non-instantaneous behavior). We will say that a behavior is non-instantaneous ↓ (κ) if: ↓ (κ2 ) ↓ (κ1 ) ↓ (κ2 ) ↓ (κ1 κ2 ) ↓ (κ1 ) ↓ (•) ↓ (φ) ↓ (κ1 ; κ2 ) ↓ (κ1 ; κ2 ) ↓ (κ1 k κ2 ) ↓ (κ1 k κ2 ) ↓ (κ1 + κ2 ) ↓ (κ) ↓ (κ) ↓ (µφ.κ) ↓ (run κ) It is important to note that function calls are not non-instantaneous. Behavior •, as expected, is noninstantaneous. Variables should also be non-instantaneous; reactivity is only checked when the variable has been instantiated. Sequential and parallel composition operators are only non-instantaneous if one of the two behaviors κ1 or κ2 is. In the case of the non-deterministic choice, the two behaviors have to be noninstantaneous as there is only one of the two behaviors that will be executed. Finally, a recursive behavior is non-instantaneous only if the body is non-instantaneous. 22
Definition 23 (Reactive behavior). We define a predicate R κ as follows: φ 6∈ R R κ1 not(↓ (κ1 )) R κ2 ) R κ1 ↓ (κ1 ) ∅ κ2 ) R φ R κ1 ; κ2 R κ1 ; κ2 R κ1 R κ2 R κ1 R κ2 R ∪ {φ} κ R κ R κ1 k κ2 R κ1 + κ2 R µφ.κ R run κ
R 0 R •
we say that a behavior κ is reactive if ∅ κ. Intuitively, predicate R κ means behavior κ is reactive with respect to the set of variables R, that is, these variables do not appear in the first instant of κ and all the recursions inside the behavior are not instantaneous. The rule for µφ.κ checks that variable φ has not been introduced in the current instant, otherwise, we would have an infinite loop. The recursion variables are then added to R. In the case of κ1 ; κ2 we remove the variables from R if κ1 is non-instantaneous. Behaviors 0, • are always reactive, and for the other operators, the reactivity is checked in the sub-expressions. Equivalence on behaviors We define an equivalence relation ≡κ , that will help to simplify the behaviors: Definition 24. Equivalence on behaviors Let ≡κ be a relation defined on the following rules: – – – –
Operators k, +, ; are idempotent and associative. Operators k, + are commutative. 0 is the neutral element of ; and k. • is the neutral element of +.
The relation also satisfies the following rules. In them, op indicates k, ; or +: κ1 ≡κ κ2 µφ.κ1 ≡κ µφ.κ2
κ1 ≡κ κ2 run κ1 ≡κ run κ2
•∞ ≡κ •
κ1 ≡κ κ01 κ2 ≡κ κ02 κ1 opκ2 ≡κ κ01 opκ02
In [15] it is also proven that ≡κ preserves reactivity: Theorem 5 (Reactivity preservation [15]). If κ1 ≡κ κ2 and R κ1 then R κ2 . A.4
Type-and-effect system for RML
In RML the link between processes and behaviors is given by a type-and-effect system. The behavior of a process becomes its effect computed using the type system. Notice that in the implementation of RML after the typechecking, all the behaviors are tested for reactivity: if all the behaviors are reactive, then the program is reactive, otherwise a warning is printed. We present the type system as follows: Types We assume a set of type variables that range over α, α1 , . . . and a set of types that ranges over τ, τ1 , . . . . We also define type schemes that range over σ, σ1 , . . . and represent universal quantifiers over type variables and behavior variables. As with behaviors, we set ftv(·) to be the set of free type variables. Furthermore, we define Γ as a context that assign types schemes to variables. Lastly, we will set ftbv(·) to be the set of free type and behavior variables of a given type. 23
Definition 25 (Types). Types are defined by the following grammar: τ, τ1 , . . . = α | T | τ1 × τ2 | τ1 → τ2 | τ process[κ] | (τ1 , τ2 ) event | hli : τi ii∈I σ, σ1 , . . . = τ | ∀α.σ | ∀φ.σ Γ = ∅ | Γ, x : σ Intuitively, a type τ is either a type variable, a base type (e.g., bool, unit), a product, a function, a process or a signal. The type of processes is parametric to its return type and its behavior. The type (τ1 , τ2 ) event of a signal is parametric to the type of the emitted value (τ1 ) and the type τ2 of the received value. The previous happens given the fact that the gathering function τ1 → τ2 → τ2 is applied. We will also allow for variant types, representing a tagged sum, where each label can have a certain type. Type schemes universally quantify over type variables and behavior variables. We define instantiation and generalization as expected: σ{τ/α} ≤ ∀α.σ
σ{κ/φ} ≤ ∀φ.σ
(Instantiation)
( τ if e is expansive gen(τ, e, Γ ) = e e ∀e α.∀φ.τ with α e, φ = ftbv(τ ) \ ftbv(Γ ) otherwise
(Generalization)
In [15], expressions that allocate signals cannot be generalized. The syntactic criterion for discriminating these expressions is by distinguishing between expansive and non-expansive ones. We say an expression e is expansive if it can allocate a signal or a reference and non-expansive otherwise. The notions of reactivity, behaviors and behavior equivalence remain the same. Type system Following [15], typing judgments are of the form Γ `r e : τ | κ. Intuitively, a judgment means that with environment Γ , expression e has type τ and behavior κ. We write Γ `r e : τ | _ ≡κ 0 when the behavior of expression e equals 0. Definition 26 (Initial typing environment). The initial typing environment Γ0 contains the types of the primitives: Γ0 = {tt : bool, ff : bool, fst :∀α1 , α2 .α1 × α2 → α1 , . . . } Intuitively, Γ0 contains all the ground types and function types. The rules for typing are defined in Fig. 13. Lastly, we will consider bool to be a variant type with two labels. This means that tt : bool = tt : htt : unit, ff : uniti and ff : bool = ff : htt : unit, ff : uniti. We now give some intuitions on the rules: – Rules (T-VAR), (T-C ON) and (T-PAIR) deal with variables, constants and pairs. Variables should instantiate the type for the variable in the environment, while constants should be an instant of base types. Lastly, pairs can only contain instantaneous actions. – Rules (T-A BS) and (T-A PP), (T-R EC) deal with abstraction, function application and recursion. They are as expected. We ask that functions and applications are instantaneous. – Rule (T-P ROC) stores the behavior of the body in the type of the process. Behavior k 0 is used to express other possible behaviors. The type system presented [15] ensures that a process has at least the behavior of its body, however, there may be other behaviors; this is what κ0 . This fact is related to subeffecting and for the scope of this paper is not necessary (for details see [15]). – Rule (T-RUN) types processes that are running. Its behavior should be stored and given by a process declaration. 24
(T-VAR )
τ ≤ Γ (x) Γ `r x : τ
(T-A BS )
|0
(T-C ON )
τ ≤ Γ0 (c) Γ `r c : τ
Γ, x : τ `r e : τ2 | 0 Γ `r λx.e : τ1 → τ2 | 0
(T-R EC )
(T-A PP )
|0 `r rec x = v : τ | 0
Γ, x : τ `r v : τ Γ
(T-RUN )
|0
(T-PAIR )
Γ `r e1 : τ1 | _ ≡κ 0 Γ `r e2 : τ2 | _ ≡κ 0 Γ `r (e1 , e2 ) : τ1 × τ2 | 0
Γ `r e1 : τ1 → τ2 | _ ≡κ 0
Γ `r e2 : τ2 | _ ≡κ 0
Γ `r e1 e2 : τ1 → τ2 | 0
(T-P ROC )
Γ `r e : τ
|κ
Γ `r process e : τ process[κ + κ0 ] | 0
Γ `r e : τ process[κ] | _ ≡κ 0
(T-PAUSE ) Γ `r pause : unit | • | run κ Γ `r e1 : τ1 | κ1 Γ `r e2 : τ2 | κ2 Γ, x1 : gen(τ1 , e1 , Γ ), x2 : gen(τ2 , e2 ) `r e3 : τ | κ3 (T-L ET ) Γ `r let x1 = e1 and x2 = e2 in e3 : τ | (κ1 k κ2 ); κ3 Γ `r e1 : τ2 | _ ≡κ 0 Γ `r e2 : τ1 → τ2 → τ2 | _ ≡κ 0 Γ, x : (τ1 , τ2 ) event `r e3 : τ | κ (T-S IG ) Γ `r signale2 x : e1 in e3 : τ | κ Γ `r e1 : (τ1 , τ2 ) event | _ ≡κ 0 Γ `r e2 : τ | κ1 Γ `r e2 : τ | κ2 (T-P RE ) Γ `r present e1 ? (e2 ) : (e3 ) : τ | κ1 + (•; κ2 ) Γ `r e1 : (τ1 , τ2 ) event | _ ≡κ 0 Γ `r e2 : τ1 | _ ≡κ 0 Γ `r e : τ | κ (T-E MIT ) (T-L OOP ) Γ `r emit e1 e2 : unit | 0 Γ `r loop e : unit | (0; κ)∞ Γ `r e1 : τ1 | κ1 Γ `r e2 : (τ1 , τ2 ) event | _ ≡κ 0 Γ, x : τ2 `r e3 : τ | κ2 (T-D O U) Γ `r do (e1 ) until e2 → (e3 ) : τ | κ1 + (•; κ2 ) Γ `r e : τ | κ φ 6∈ fbv(Γ, τ ) Γ `r e1 : τ1 | κ Γ `r e2 : (τ1 , τ2 ) event | _ ≡κ 0 (T-M ASK ) (T-D OW) ∞ Γ `r do e1 when e2 : τ | κ + • Γ `r e : τ | κ{•/φ} Γ `r c : hli : τi ii∈I | 0 Γ `r ei : τ | κi for each i (T-M ATCH ) P Γ `r match c with {ci → ei }i∈I : τ | i∈I κi Γ `r run e : τ
Fig. 13. Typing rules for RML processes.
– Rule (T-PAUSE) types the pause operator with type unit and non-instantaneous behavior. – Rule (T-L ET) types let processes as expected (each branch). – Rule (T-S IG) types the signal declaration operator. Notice the type of the gathering function τ1 → τ2 → τ2 , as well as the fact that the variable x is added with a signal type in the environment. – In Rule (T-P RE) notice that there are two possibilities: the behavior of e2 can be executed right away or the behavior of e3 will be executed in the next time unit. Hence the behavior to check is κ1 + (•; κ2 ). – Rule (T-E MIT) is as expected, considering that the emission is instantaneous. – Rule (T-L OOP) types loops, by checking that the behavior is infinite. – Rule (T-D O U) is the same as Rule (T-P RE). – Rule (T-D OW) types a process that will execute some behavior instantaneously or will execute a behavior that will do nothing while waiting for a given signal. – Rule (T-M ASK) allows to simplify effect expressions, by using what is called effect masking. Notice that if a behavior variable appearing in some behavior κ is free in the environment, it is not constrained; 25
therefore, we can give it any value. In particular, in [15], the authors choose to replace it with •, which is the neutral element of +, allowing it to be simplified. – Ruule (T-M ATCH) verifies that the constant c used for matching is of a variant type, and proceed to type each possible continuation. Lastly, we will introduce a form of weakening in our type system: Lemma 1 (Weakening for `r ). If Γ, x : τ `r e : τ 0 | κ and x 6∈ fv(e) then Γ `r e : τ 0 | κ Proof. The proof proceeds by induction on the typing derivation. We show one case in which variables are added to the environment, all the other cases proceed similarly. Our base case is Rule (T-VAR), that is trivial, since e = x and fv(x) = {x}: 1. (T-A BS): Suppose that: (T-A BS )
Γ, y : τ 0 , x : τ `r e : τ2 | 0 Γ, y : τ 0 `r λx.e0 : τ1 → τ2 | 0
where y 6∈ fv(λx.e0 ). There are two cases: (a) y = x: We use renaming of bound variables in λx.e0 to change x into some z 6∈ dom(Γ ) and we apply the Rule (T-A BS). By the inductive hypothesis, conclude. (b) y 6= x: Conclude by the inductive hypothesis.
A.5
Additional transition rules for RMLq
Fig. 14, Fig. 15 and Fig. 16 present the transition rules for RMLq. They are based on the rules presented in Fig. 11 and Fig. 12. However, the rules in this setting are applied to configurations, rather than processes; furthermore, configurations are pairs composed of processes P and sets of queues (i.e., states) Σ. States contain information about the queues and the elements that populate them. Queues are collected through the derivation three using a point-wise union on sets Σ1 ∪ Σ2 . To avoid issues regarding nondeterminism in order of queues we will not allow the execution of two put / pop operators (or the combination of both) on the same queue in parallel during the instant. This effectively means that only one thread will have control of that queue (i.e., the thread has a lock on the queue) at any given instant. In constructs with continuation such as the let operator, it is reasonable to let the continuations use the queues modified by the expressions evaluated before the continuation is executed. Thus, let x = e1 and y = e2 in e3 will first execute e1 and e2 with states Σ1 and Σ2 in parallel and the continuation e3 will use Σ1 ∪ Σ2 in its execution.
B B.1
Appendix for Section 4 Proof of Thm. 1 in Page 12
The statement is a corollary of proving the correctness properties in Def. 12 for J·Kf (namely, name invariance, compositionality, and operational correspondence). 26
bPAUSEc
bR ECURc E,tt hv{x/rec x = v} ; Σi 9999K hv 0 ; Σ1 i
bVALc
S
∅,ff
hpause ; Σi 9999K h() ; Σi S
E,tt
∅,tt
hrec x = v ; Σi 9999K hv 0 ; Σ1 i
hv ; Σi 9999K hv ; Σi
S
S
E1 ,tt
0
he ; Σi 99999K hprocess e ; Σ1 i
00
he ; Σ1 i 9999K he ; Σ2 i
S
bRUNc
E2 ,b
0
S
E1 tE E2 ,b
00
hrun e ; Σi 99999999K he ; Σ2 i S
bA PPLc E1 ,tt
E2 ,tt
he2 ; Σi 99999K hv 0 ; Σ2 i
he1 ; Σi 99999K hλx.e3 ; Σ1 i S
S E1 tE E2 tE E3 ,tt
E3 ,tt
he3 {x/v 0 } ; Σ1 ∪ Σ2 i 99999K hv ; Σ3 i S
he1 e2 ; Σi 9999999999999K hv ; ∪Σ3 i S
bL-PARc E1 ,b1
E2 ,b2
he1 ; Σi 99999K he01 ; Σ1 i
he2 ; Σi 99999K he02 ; Σ2 i b1 ∧ b2 = ff
S
S
E1 tE E2 ,ff
hlet x1 = e1 and x2 = e2 in e3 ; Σi 999999999K hlet x1 = e01 and x2 = e02 in e3 ; Σ1 ∪ Σ2 i S
E1 ,tt
he1 ; Σi 99999K hv1 ; Σ1 i S
E2 ,tt
he2 ; Σi 99999K hv2 ; Σ2 i S
E3 ,b
he3 {x1 , x2/v1 , v2 } ; Σ1 ∪ Σ2 i 9999K he03 ; Σ3 i S E1 tE E2 tE E3 ,b
bL-D ONEc
let x1 = e1 and x2 = e2 in e3 999999999999K he03 ; Σ3 i S
E1 ,tt
he1 ; Σi 99999K hn ; Σ1 i n ∈ S S
bS IG -Pc
E2 ,b
he2 ; Σ1 i 9999K he02 ; Σ2 i S
E1 tE E2 ,b
hpresent e1 ? (e2 ) : (e3 ) ; Σi 99999999K he02 ; Σ2 i S
E,tt
he1 ; Σi 9999K hn ; Σ1 i n 6∈ S bS IG -NPc
S
E,ff
hpresent e1 ? (e2 ) : (e3 ) ; Σi 9999K he3 ; Σ1 i S
Fig. 14. Big-step semantics for RMLq expressions.
Name invariance Theorem 6 (Name invariance for J·Kf ). For every π process P , substitution σ and renaming function f such that dom(f ) ⊆ ran(σ) it holds that JP σKf = JP Kg σ where dom(g) ⊆ dom(σ) and ran(f ) = ran(g). In this property, we should consider the substitutions made by the renaming function f . Notice that some of the free names of P in the LHS of JP σKf = JP Kg σ will be first modified by σ and then by f , whereas in the RHS they will be first modified by g and then by σ. This is why g must have the same range as f and its domain should be a subset of dom(σ), ensuring that after both substitutions the terms remain equal. We proceed with the proof of the statement. Proof. The proof proceeds by induction on the structure of P : 27
E1 ,tt
E2 ,tt
he1 ; Σi 99999K hv1 ; Σ1 i
he2 ; Σi 99999K hv2 ; Σ2 i
S
bPAIRc
S
E1 tE E2 ,tt
h(e1 , e2 ) ; Σi 999999999K h(v1 , v2 ) ; Σ1 ∪ Σ2 i S
E1 ,tt
E2 ,tt
he1 ; Σi 99999K hn ; Σ1 i
he2 ; Σi 99999K hv ; Σ2 i
S
bE MITc
S
E1 tE E2 tE [{v}/n],tt
hemit e1 e2 ; Σi 9999999999999999K h() ; Σ1 ∪ Σ2 i S
E,tt
he2 ; Σi 9999K hn ; Σ1 i S
bDW-NSc
n 6∈ S
E,ff
hdo e1 when e2 ; Σi 9999K hdo e1 when n ; Σ1 i S
E2 ,tt
he2 ; Σi 99999K hn ; Σ1 i n ∈ S S
bDW-I NTc
E1 ,ff
he1 ; Σ1 i 99999K he01 ; Σ2 i S
E1 tE E2 ,ff
hdo e1 when e2 ; Σi 999999999K hdo S
E2 ,tt
he2 ; Σi 99999K hn ; Σ1 i n ∈ S S
bDW-E NDc
e01
when n ; Σ2 i E1 ,tt
he1 ; Σ1 i 99999K hv ; Σ2 i S
E1 tE E2 ,tt
hdo e1 when e2 ; Σi 999999999K hv ; Σ1 i S
bL P -U Nc
bL P -S TUc E,ff
he ; Σi 9999K he0 ; Σ1 i S E,ff
E1 ,tt
he ; Σi 99999K hv ; Σ1 i S
E2 ,b
hloop e ; Σ1 i 9999K he0 ; Σ2 i S
E1 tE E2 ,b
0
hloop e ; Σi 9999K he ; loop e ; Σ1 i
0
hloop e ; Σi 99999999K he ; Σ2 i
S
S
Fig. 15. Big-step semantics for RMLq expressions.
Case 1 (P = 0). J0Kf = (), for every f
(By Fig. 6)
(1)
0σ = 0, for every σ
(fn(0) = ∅ )
(2)
J0σKf = J0Kf = () = J0Kf σ, for every f
(By Fig. 6)
(3)
Case 2 (P = xhvi.Q). Let us consider the set of free names of P . We have two cases depending on whether v is a constant or not: Subcase 1 (v is a constant). We proceed with a direct proof. fn(P ) = {x} ∪ fn(Q)
(By fn(·) )
(1)
Let u ˜ = {u1 , . . . , x, . . . un }, n ≥ 1 and σ be a translation. Then x ∈ dom(σ) ∨ x 6∈ dom(σ) Subsubcase 1 (x ∈ dom(σ)). Assume, w.l.o.g σ(x) = x ˆ: σ = {y1 , . . . , xˆ, . . . , yn/u1 , . . . , x, . . . , un }
(Assumption)
(2)
f = {u1 ← z1 , . . . , x ˆ ← zi , . . . , um ← zm }, 1 ≤ i ≤ m ≤ |˜ u|
(Assumption)
(3)
P σ = xhvi.Qσ = x ˆhvi.(Qσ)
(Applying σ )
(4)
28
E2 ,tt
E1 ,tt
he2 ; Σi 99999K hn ; Σ1 i
he1 ; Σ1 i 99999K hv ; Σ2 i
S
bDU-E NDc
S E1 tE E2 ,tt
hdo (e1 ) until e2 (x) → (e3 ) ; Σi 999999999K hv ; Σ2 i S
E2 ,tt
E1 ,ff
he1 ; Σ1 i 99999K he01 ; Σ2 i
he2 ; Σi 99999K hn ; Σ1 i n ∈ S bDU-Pc
S
S
E t E ,ff
v 1 E 2 hdo (e1 ) until e2 (x) → (e3 ) ; Σi 999999999K he3 {S (n)/x} ; Σ2 i S
E2 ,tt
E1 ,ff
he1 ; Σ1 i 99999K he01 ; Σ2 i
he2 ; Σi 99999K hn ; Σ1 i n 6∈ S S
bDU-NPc
S
E1 tE E2 ,ff
hdo (e1 ) until e2 (x) → (e3 ) ; Σi 999999999K hdo S
E1 ,tt
he1 ; Σi 99999K hv1 ; Σ1 i S
(e01 )
until e2 (x) → (e3 ) ; Σ2 i
E2 ,tt
he2 ; Σi 99999K hv2 ; Σ2 i S
E3 ,b
he3 {x/n} ; Σ1 ∪ Σ2 i 9999K he03 ; Σ3 i n fresh S(n) = (v1 , v2 , m) S
bS IG -D ECc
E1 tE E2 tE E3 ,b
hsignale2 x : e1 in e3 ; Σi 999999999999K he03 ; Σ3 i S
∅,tt
he ; Σi 9999K hcj ; Σ1 i j ∈ I S
bC ASEc
E,b
hej ; Σ1 i 999K he0j ; Σ2 i S
E,b
hmatch e with {ci → ei }i∈I ; Σi 999K he0j ; Σ2 i S
Fig. 16. Transition for RMLq expressions (cont.)
By Def. 6 consider: JP σKf = signal x0 in emit zi (v, x0 ); pause ; JQσKf,{zi ←x0 }
(5)
Now, let g = {y1 ← z1 , . . . , x ← zi , . . . , ym ← zm }, 1 ≤ i ≤ m ≤ |˜ u| and consider: JP Kg σ = signal x0 in emit zi (v, x0 ); pause ; (JQKg,{zi ←x0 } )σ JQσKf,{zi ←x0 } = (JQKg,{zi ←x0 } )σ JP σKf = JP Kg σ
(6)
(I.H)
(7)
(By (5),(6),(7))
(8)
Subsubcase 2 (x 6∈ dom(σ)). This case is straightforward by applying the I.H. Subcase 2 (v is a variable). This proof proceeds as above, considering v inside the possible substitutions. Case 3 (All other cases for P ). They proceed as above, taking into account the possible free variables for each process. t u Compositionality Theorem 7 (Compositionality of J·K f ). Let P and E[·] be a π process and an evaluation context (cf. Def. 2), respectively. Then JE[P ]Kf = JEKf JP Kg , for some f, g. 29
Proof. By case analysis on E[·] and each case by induction on the structure of P , using Def. 2: Case 1 (E = P | R). By induction on the structure of P , we only analyze the cases for inaction, output and input: Subcase 1 (P = 0). As follows: E[P ] = 0 | JRKf
JE[P ]Kf = () k JRKf for any f JEKf JP Kf = () k JRKf for any f JEKf JP Kf = JE[P ]Kf
(Assumption)
(1)
(Fig. 6)
(2)
(Fig. 6)
(3)
(By (2),(3))
(4)
Subcase 2 (P = xhvi.P ). As follows:
E[P ] = xhvi.P | JRKf
(Assumption)
(1)
(Fig. 6)
(2)
(Fig. 6)
(3)
(By (2),(3))
(4)
E[P ] = x(y).P | R
(Assumption)
(1)
JE[P ]Kf = Jx(y).P Kf k JRKf for any f JEKf JP Kf = Jx(y).P Kf k JRKf for any f JEKf JP Kf = JE[P ]Kf
(Fig. 6)
(2)
(Fig. 6)
(3)
(By (2),(3))
(4)
JE[P ]Kf = Jxhvi.P Kf k JRKf for any f JEKf JP Kf = Jxhvi.P Kf k JRKf for any f JEKf JP Kf = JE[P ]Kf
Subcase 3 (P = x(y).P ). As follows:
Subcase 4 (All other processes). The proof is analogous to the previous ones. Case 2 (E = R | V ). As above. Case 3 (E = (νxy)P ). By induction on the structure of P , we show the cases for inaction, input and output: Subcase 1 (P = 0). As follows: E[P ] = (νxy)0 ≡S 0
(Assumption, ≡S )
(1)
JE[P ]Kf = signal c in J0Kf,{x←c,y←c}
(Fig. 6)
(2)
(Fig. 6)
(3)
(By (2),(3))
(4)
Let g = f, {x ← c, y ← c} : JEKf JP Kg = signal c in J0Kg JEKf JP Kg = JE[P ]Kf
Subcase 2 (P = xhvi.P ). As follows:
E[P ] = (νzw)xhvi.P
(Assumption)
(1)
JE[P ]Kf = signal c in JP Kf,{x←c,y←c}
(Fig. 6)
(2)
(Fig. 6)
(3)
(By (2),(3))
(4)
Let g = f, {x ← c, y ← c} : JEKf JP Kg = signal c in JP Kg JEKf JP Kg = JE[P ]Kf
30
Subcase 3 (P = x(y).P ). As follows: E[P ] = (νzw)x(y).P
(Assumption)
(1)
JE[P ]Kf = signal c in JP Kf,{z←c,w←c}
(Fig. 6)
(2)
(Fig. 6)
(3)
(By (2),(3))
(4)
Let g = f, {z ← c, w ← c} : JEKf JP Kg = signal c in JP Kg JEKf JP Kg = JE[P ]Kf
t u Operational correspondence Before stating the operational correspondence statement we proceed by providing some auxiliary definitions: Definition 27 (Prefixed Processes and Redexes). We say processes xhvi.P , x(y).P , x/l.P , x.{li : Pi }i∈I , and ∗ x(y).P are pre-redexes prefixed at x. Furthermore, we will call processes x(y).P , x . {li : Pi }i∈I and ∗ x(y).P input-like. Redexes are processes of the form xhvi.P | y(z).Q, xhvi.P | ∗ y(z).Q, or x / lj .P | y . {li : Qi }i∈I , with j ∈ I.
Definition 28 (Well-formed π processes). Process P is well-formed if for each of its structural congruent processes of the form (ν x eye)(Q | R | S) the following conditions hold: 1. If Q = v? (Q1 ) : (Q2 ) then v ∈ {tt, ff}. 2. If Q and R are prefixed on the same variable then they are input-like of the same nature. 3. If Q is prefixed on x1 ∈ x e and R is prefixed on y1 ∈ ye then Q | R is a redex.
Theorem 8 (Operational Correspondence). Let C[P ] be a well-formed π process (cf. Def. 28) with C[·] = (ν x eye)(· | S). Then: 1. Soundness: If C[P ] −→ C[Q] then JC[P ]Kf 7−→,→R JC 0 [Q]Kf and C[Q] −→∗ (ν x eye)C 0 [Q], for some C 0 , f . 2. Completeness: If JC[P ]Kf 7−→ R then there exist Q and C 0 [·] such that R ,→R JC 0 [Q]Kf and C[P ] −→∗ (ν x eye)C 0 [Q]. Proof. We prove each item: 1. Soundness: The proof proceeds by induction on the reduction and a case analysis on the last applied rule: Case 1 (Rule bI F Tc). Assume C[P ] −→ C[Q] with Rule bI F Tc. C[P ] ≡S (ν x eye)(tt? (Q) : (R) | S)
(Assumption)
(1)
C[P ] −→ (ν x eye)(Q | S)
(Fig. 1)
(2)
31
By applying J·Kf to (1): JC[P ]Kf = signalh e c : (_, _) in JP | SKg
= signalh e c : (_, _) in (if tt then pause ; JQKf else pause ; JRKf ) k JSKg ∅,tt
Using Rule bC ASEc from Fig. 4 we see that JC[P ]Kf −−→ JQKf . G
We now analyze JSKg . By Def. 28, we know that either: (a) S is a redex (or) (b) S ≡S x(y).S 0 (or) (c) S ≡S x . {li : Si0 }i∈I (or) (d) S ≡S ∗ x(y).S 0 . We analyze each of these cases:
E,ff
(a) Subsubcase 1 (S is a redex). Then there exist E, G, S 0 such that JSKf −−−→ JS 0 Kg , such that G
S −→ S 0 . Since S is a redex, we apply a case analysis on the rules in Fig. 1: – Subsubsubcase 1 (Rule bI F Tc). We build a derivation as above. – Subsubsubcase 2 (Rule bI F Fc). We build a derivation as above, but instead of tt we use ff and apply Rule bC ASEc. – Subsubsubcase 3 (Rule bC OMc). We build a derivation tree as follows; we only observe process: (νxy)(xhvi.S 0 | y(z).S 00 ) assume a signal environment G with all the necessary signals initialized. Then, we will show that E,b J(νxy)(xhvi.S 0 | y(z).S 00 )Kf −−→ JS 0 Kg0 | JS 00 Kg00 {v/z } G
for some E, b, g. Applying J·Kf (Fig. 6): J(νxy)(xhvi.S 0 | y(z).S 00 )Kf =signalh c : (_, _) in
signalh x0 : (_, _) in emit c (v, x0 ); pause ; JS 0 Kg0 k await c(z, α) in JS 00 Kg00
where g 0 = f, {x ← c, y ← c}, {x ← x0 } and g 00 = f, {x ← c, y ← c}, {y ← α}. For the derivation tree we apply Rule bS IG -D ECLc and then Rule bL-PARc (cf. Fig. 4) to split the encoded process into: