type-safe evolution of data-centric applicationsmiguel.domingues.pt/docs/techreport-2014.pdf ·...

27
Type-Safe Evolution of Data-Centric Applications Technical Report (extended version with proofs) Miguel Domingues Jo˜ ao Costa Seco CITI – Universidade Nova de Lisboa Abstract This paper introduces a uniform, language-based reconfiguration mechanism for data-centric applications, that supports a novel and flexible style of live programming. Our programming model sup- ports the incremental construction and maintenance of applications, by means of verified operations, applied to running instances of software systems. We allow for the seamless, type-safe, evolution and reconfiguration of both application logic and persistent state. Which means that applications may evolve without any service dis- ruption. We use a data-flow reactive language semantics that safely combines imperative constructs with a reactive context. Our type system ensures the change propagation process through the data dependencies graph, and the reconfiguration of applications are sound. We also prove that type safety implies the convergence of the propagation process, which is essential to correctly implement the reactive behavior of applications. 1. Introduction Flexible development frameworks and agile development method- ologies are gaining in popularity, especially in the domain of web (data-centric) applications. However, the promised incremental and flexible design comes at a price, it is often the case that a large amount of effort is wasted in the redefinition and refactorization of existing code. There are methodologies and development tools that provide mechanisms to soundly perform refactoring applications, but they do not avoid the burden that a code or data-schema update may cause. Updates in running systems usually mean significant service downtime, and often require explicitly programmed scripts to handle the evolution of persistent data. We aim at providing an effective incremental mechanism, that allows safe updates of both application code and data, without causing any sort of service dis- ruption. We set our programming model in a context where the design of reactive software architectures is increasingly important. A usual requirement for web and cloud applications, as well as in other [Copyright notice will appear here once ’preprint’ option is removed.] models [1], is that data changes are automatically transported from the application’s persistent data layer to the (active) user interfaces. This kind of reactive behavior is usually defined by ad-hoc hand- crafted code, which is more complex to write and verify, in the presence of distribution and collaborative applications. Our pro- gramming language uses suitable language abstractions to capture the reactive nature of data-centric applications, thus allowing a typ- ing verification to reason about its properties. Our attention is drawn to the problem of how to make the evolu- tion of reactive data-centric applications less time consuming and error-prone. Current development environments are already imple- menting immediate feedback and preview features, as a crucial fac- tor for productivity. We aim at pushing that frontier even further, by providing a style of incremental [6, 18, 25] and live [5] program- ming, that captures a core set of construction operations on running systems. Our approach allows developers to continuously evolve an application, by changing its code [8, 11, 20], and reconfiguring the underlying data [2, 13], in a seamless development process. We introduce a reactive programming language, that presents an ab- straction level suitable for building data-centric (imperative) appli- cations, where it is possible to establish a dynamic reconfiguration semantics, of both application code and data. In our language, we have three key ingredients to model our target scenario of data-centric applications: state variables, data transformation expressions, and actions. State variables are used to model the persistent layer of the application, data transformation expressions model the logic that queries data and presents the user with web pages, and actions, that enclose imperative updates to the data layer. In our model, actions are monad-like values that repre- sent delayed imperative computations, and are typically linked to event handlers (UI). The language that we use to model the appli- cation logic is a lambda-calculus with collections and records, that we can compositionally change to a more expressive fragment. We follow the model of having a systems’ console to manage, and in our case build, the evolution of a system (cf. [19, 20]). For each of these key ingredients, we define a corresponding top-level opera- tion to be interpreted at the systems’ console. The operations are: the declaration of state variables (var), the declaration of pure data transformations (def ), and the explicit execution (do) of actions (action). This model is partially inspired by the usual architec- tures and conventions of web applications, where the resources of a system (named values) are obtained through GET requests using URIs, and execution of actions correspond to the handling of user actions (cf. POST requests). Changes to the state of the applica- tion, caused only by the execution (do) of actions, are implicitly and automatically propagated through the definitions of pure data transformation elements, thus updating their computed values (cf. a data-driven operational semantics [12]). Data dependencies be- tween named elements form a data-flow graph that defines how changes are propagated throughout. This data-flow graph is built 1 2014/6/9

Upload: others

Post on 22-May-2020

2 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Type-Safe Evolution of Data-Centric Applicationsmiguel.domingues.pt/docs/techreport-2014.pdf · Which means that applications may evolve without any service dis-ruption. We use a

Type-Safe Evolution of Data-Centric ApplicationsTechnical Report (extended version with proofs)

Miguel Domingues Joao Costa SecoCITI – Universidade Nova de Lisboa

AbstractThis paper introduces a uniform, language-based reconfigurationmechanism for data-centric applications, that supports a novel andflexible style of live programming. Our programming model sup-ports the incremental construction and maintenance of applications,by means of verified operations, applied to running instances ofsoftware systems. We allow for the seamless, type-safe, evolutionand reconfiguration of both application logic and persistent state.Which means that applications may evolve without any service dis-ruption.

We use a data-flow reactive language semantics that safelycombines imperative constructs with a reactive context. Our typesystem ensures the change propagation process through the datadependencies graph, and the reconfiguration of applications aresound. We also prove that type safety implies the convergence ofthe propagation process, which is essential to correctly implementthe reactive behavior of applications.

1. IntroductionFlexible development frameworks and agile development method-ologies are gaining in popularity, especially in the domain of web(data-centric) applications. However, the promised incremental andflexible design comes at a price, it is often the case that a largeamount of effort is wasted in the redefinition and refactorization ofexisting code. There are methodologies and development tools thatprovide mechanisms to soundly perform refactoring applications,but they do not avoid the burden that a code or data-schema updatemay cause. Updates in running systems usually mean significantservice downtime, and often require explicitly programmed scriptsto handle the evolution of persistent data. We aim at providing aneffective incremental mechanism, that allows safe updates of bothapplication code and data, without causing any sort of service dis-ruption.

We set our programming model in a context where the design ofreactive software architectures is increasingly important. A usualrequirement for web and cloud applications, as well as in other

[Copyright notice will appear here once ’preprint’ option is removed.]

models [1], is that data changes are automatically transported fromthe application’s persistent data layer to the (active) user interfaces.This kind of reactive behavior is usually defined by ad-hoc hand-crafted code, which is more complex to write and verify, in thepresence of distribution and collaborative applications. Our pro-gramming language uses suitable language abstractions to capturethe reactive nature of data-centric applications, thus allowing a typ-ing verification to reason about its properties.

Our attention is drawn to the problem of how to make the evolu-tion of reactive data-centric applications less time consuming anderror-prone. Current development environments are already imple-menting immediate feedback and preview features, as a crucial fac-tor for productivity. We aim at pushing that frontier even further, byproviding a style of incremental [6, 18, 25] and live [5] program-ming, that captures a core set of construction operations on runningsystems. Our approach allows developers to continuously evolve anapplication, by changing its code [8, 11, 20], and reconfiguring theunderlying data [2, 13], in a seamless development process. Weintroduce a reactive programming language, that presents an ab-straction level suitable for building data-centric (imperative) appli-cations, where it is possible to establish a dynamic reconfigurationsemantics, of both application code and data.

In our language, we have three key ingredients to model ourtarget scenario of data-centric applications: state variables, datatransformation expressions, and actions. State variables are usedto model the persistent layer of the application, data transformationexpressions model the logic that queries data and presents the userwith web pages, and actions, that enclose imperative updates to thedata layer. In our model, actions are monad-like values that repre-sent delayed imperative computations, and are typically linked toevent handlers (UI). The language that we use to model the appli-cation logic is a lambda-calculus with collections and records, thatwe can compositionally change to a more expressive fragment. Wefollow the model of having a systems’ console to manage, and inour case build, the evolution of a system (cf. [19, 20]). For each ofthese key ingredients, we define a corresponding top-level opera-tion to be interpreted at the systems’ console. The operations are:the declaration of state variables (var), the declaration of pure datatransformations (def ), and the explicit execution (do) of actions(action). This model is partially inspired by the usual architec-tures and conventions of web applications, where the resources ofa system (named values) are obtained through GET requests usingURIs, and execution of actions correspond to the handling of useractions (cf. POST requests). Changes to the state of the applica-tion, caused only by the execution (do) of actions, are implicitlyand automatically propagated through the definitions of pure datatransformation elements, thus updating their computed values (cf.a data-driven operational semantics [12]). Data dependencies be-tween named elements form a data-flow graph that defines howchanges are propagated throughout. This data-flow graph is built

1 2014/6/9

Page 2: Type-Safe Evolution of Data-Centric Applicationsmiguel.domingues.pt/docs/techreport-2014.pdf · Which means that applications may evolve without any service dis-ruption. We use a

in such a way, that imperative code (variable initialization and as-signments) is kept apart from the change propagation process. Inthis way, we statically certify the safe use of imperative constructsin a reactive context, by ensuring the absence of infinite changepropagation loops.

In summary, we provide a flexible style of live programming,where applications are incrementally built and maintained by se-quences of type-safe operations. To the best of our knowledge, thisis the first work combining a type-safe reactive and imperative lan-guage, with a statically verified dynamic reconfiguration mecha-nism. Our key contributions can be summarized as follows:

• a novel core reactive language for data-centric applications, thatsupports type-safe dynamic reconfiguration.• a data-flow operational semantics supporting the synchronized

evolution of both code and data.• a type system that statically ensures the safety of applications

in the presence of both reactive propagation of changes anddynamic reconfiguration operations.• type preservation and progress results that include the conver-

gence of change propagation.

The remainder of this paper is structured as follows. Section 2introduces our programming language by means of a small exam-ple. Another example, yet more realistic, is presented in Section 3.In Section 4, we formally present our core reactive and imperativeprogramming language, its operational semantics and type system.We then extend our programming language, in Section 5, to supportdynamic reconfiguration. Section 6 states the soundness propertiesof our language, and also sketches the corresponding proofs. Sec-tions 8 and 9 provide a comparison with related work, and a finaldiscussion on our work.

2. Incremental Reactive ProgrammingWe now define our reactive and incremental computational model.This model is designed to host a running instance of a data-centricapplication, comprising both application logic and persistent state.Applications are incrementally built by a set of top-level construc-tion operations, that enable the safe definition and deployment ofnamed programming elements, and basic interaction with the appli-cation persistent state. Existing named programming elements mayalso be redefined using the same top-level construction operations,thus allowing to dynamically reconfigure the application.

Our programming language comprises two named program-ming elements: state variables (var) and pure data transforma-tions (def ). State variables correspond to the application persis-tent state, and pure data transformations correspond to the appli-cation’s logic. Together, these elements form a data-flow graphbased on the dependencies between the usage of names. This de-pendency graph enable us to propagate changes between elements,i.e. changes occurring at the application persistent state are imme-diately and seamlessly propagated into pure data transformation el-ements. By propagating changes, all named elements are alwayskept up-to-date with respect to the application persistent state. Notethat changes are not propagated into state variables (i.e. persistentstate). The application persistent state is only changed by the ex-plicit execution (do) of imperative statements (action).

Consider the example from Figure 1. On the left-hand side wepresent a sequence of operations that declare state variables (var),pure data transformations (def ), and execution of actions (do).On the right-hand side we show the corresponding data-flow graphbuilt according to the name dependencies between programmingelements. The operations in lines 1 to 3, define names a, b, and cdenoting values 0, 1, and 1, respectively. Notice that a is a state

1. var a = 02. def b = a + 13. def c = a + b4. do action { a := a + b }5. def b = a + 2

a

b

c

Figure 1. Example.

variable, and names b and c are pure data transformations. The un-derlying data-flow graph is incrementally built, along with the ap-plication’s programming elements definitions, and kept up-to-datewith relation to the name usage of the defined names. In the data-flow graph of Figure 1, nodes correspond to programming elements(either var or def ), and edges represent name dependencies, andare directed to denote the propagation of changes. Edges are estab-lished, and added to the data-flow graph, based on the definition ofeach name. For instance, name c is defined by expression a + b,resulting in two edges, one from a to c, and another from b to c.Notice that, in order to ensure the convergence of the change prop-agation, we must ensure that the data-flow graph is acyclic. Thisis statically ensured by our type system (presented in Section 4.2),and is one of our final results, expressed in Theorem 3 (Section 6).Notice that the expressivness of the language is not limited by theacyclic property of the graph, because the application logic can beconcentrated in the data transformation expressions, similarly toweb application actions.

In line 4, there is an operation do over an action value con-taining the assignment statement a := a + b. The execution ofthis action changes the value of the state variable a. Recall thatthe contents of state variables (var) can only be changed by theexecution (do) of action values, which contain sequences of de-layed imperative statements. After changing state variable a, thenew value will be propagated through the graph, and the values de-noted by b and c are reactively updated. When the propagation ofchanges terminates, names a, b, and c will denote the values 1, 2and 3, respectively. Pure data transformations (def ) are reactivelyupdated when there are changes in the values of the names theydepend on. This implies that initializer expressions of pure datatransformations (def ) are re-evaluated during the propagation ofchanges. However, initializer expressions of state variables (var)and assignment statements enclosed by action values are ignoredduring the propagation of changes.

This style of incremental programming enable us to evolve ap-plications in a safe manner. We are able, not only to add new pro-gramming elements, but also to redefine the existing ones. Con-sider the operation in line 5. It redefines the expression associatedto name b, thus changing its denotation by evaluating the new ex-pression, and propagating its new value through the dependencygraph. After propagating this change, name a remains unchangedwith value 1, and names b and c now denote 3 and 4, respectively.Notice that the assignment operation (line 4) is not executed again,even if it uses b. This effect is controlled by the distinction be-tween visible names, and delayed imperative statements enclosedin action values. Notice

3. ExampleConsider the small, and yet more realistic, example of a bulletinboard application, whose user interface is illustrated in Figure 3.This user interface is built using the following elements: a list ofmessages with data retrieved from a database; a “thumbs-up” iconfor each element in the list, linked to a request that increments acounter of “likes” for each message; a text box that accepts text for

2 2014/6/9

Page 3: Type-Safe Evolution of Data-Centric Applicationsmiguel.domingues.pt/docs/techreport-2014.pdf · Which means that applications may evolve without any service dis-ruption. We use a

varmessages =

id : 0,author : “Paul”,message : “Hi there! ...”,likes : 10

::[...]

def size = iter(messages, 0, x.y.(y + 1))

def new = λa.λm.action {messages := messages@[

id : size,author : a,message : m,likes : 0

] }

def like = λid.action {messages := [m.id = id ?

id : m.id,author : m.author,message : m.message,likes : m.likes+ 1

: m | m← messages ] }

def wall = [

{message : m,incLikes : like m.id

}| m← messages ]

Figure 2. Bulletin Board Code.

7:11 PM

PaulHi there! wanna go out tonight?

HenryCool! Where to?

10

0

I’ll pick you up at 6.

Post message Clear filter

MaryLet’s go to the movies!

PaulGreat idea, Startrek is on again!

3

8

Figure 3. Bulletin Board UI Mockup.

a new message; and a button with label “Post message”, linked to arequest to add a new message.

We illustrate the sequence of construction operations that maybe used to support such user interface (see Figure 2 for the fullprogram). Starting from an empty system, we first need to definethe persistent state of the application. In this case, we need to definea state variable containing a collection of messages (records), withoperation

varmessages =

id : 0,author : “Paul”,message : “Hi there! ...”,likes : 10

::[...]

Each element of the collection in state variable messages containsa message identifier (id), the author’s name, the message text,

and the number of likes for each message. Name messages is nowavailable to be used in other definitions, for instance, we can write

def size = iter(messages, 0, x.y.(y + 1))

to compute the size of the collection, which is bound to name size,and is always up-to-date with relation to the contents of state vari-able messages. The iter expression iterates over the collection us-ing a fold-left semantics. In the iteration body (x.y.(y + 1)), vari-able x denotes the current element of the collection, and variable ydenotes the computed result in the previous iteration, or the initialvalue (0).

At this stage, these names, can conceivably be accessed througha conventioned URL, to be used in a web interface such as the onein Figure 3.

To add a new message, one may use the operation

doaction { messages := messages@[m] }where m is a message that is added to the collection. We canabstract this operation using a function like

def new = λa.λm.letmsg =

id : size,author : a,message : m,likes : 0

in

action { messages := messages@[msg ] }

and then link the button “Post message” in the user interface,through a POST request with arguments, to the execution of

do (new “Paul” “I’ll pick you up at 6.”)

Notice that the definition of new uses name size to assign anidentifier to the new message, which is always up-to-date withrelation to the collection stored in messages.

In order to continue building the list shown in the user interface,we need to add some active behavior to the “thumbs-up” icon, foreach row. So, we need to define a function that increments thecounter of a message.

def like =

let inc = λx.

id : x.id,author : x.author,message : x.message,likes : x.likes+ 1

in

λid .action { messages :=[m.id = id ? (incm) : m | m← messages ] }

3 2014/6/9

Page 4: Type-Safe Evolution of Data-Centric Applicationsmiguel.domingues.pt/docs/techreport-2014.pdf · Which means that applications may evolve without any service dis-ruption. We use a

P ::= O1, . . . ,On

O ::= def a = e | var a = e | do e

e ::= a | b | x | λx:τ.e | e e′ | e op e′ | e ? e′ : e′′

| [e1, . . . , en] | iter(e, e′, x.y.e′′)| match e with x::xs→ e′ | [ ]→ e′′

| action { a := e }

Figure 4. Programming Language.

Function like takes a message identifier (id) and iterates the col-lection messages using a for-comprehension style [21], and incre-ments the counter of the selected message. We can now use thisdefinition to produce a collection suitable for displaying messagesin the user interface, together with the intended behavior.

def wall =

[

{message : m,incLikes : like m.id

}| m← messages ]

This definition produces a collection that contains a message andan action value, for each row. Each action is a closure that con-tains the identifier for the message in the same row. By clicking onthe “thumbs-up” icon, one triggers the execution (do) of the ac-tion, and thus increments the corresponding counter. So, the list ofmessages shown in the user interface in Figure 3 corresponds toaccessing name wall.

Whenever the state of the application is changed, the collec-tion defined by name wall is updated, and the new values can bepushed to the user interface. In summary, by adding a new mes-sage or clicking a “thumbs-up” icon of a message, the state variablemessages is modified, causing the propagation of changes to thenames that depend on it (i.e. size and wall), thus refreshing them.We think that this illustrates the semantic separation between thereactive and imperative parts of our language.

4. Programming LanguageOur programming language, presented in Figure 4, consists in top-level declaration and interaction operations (O), and a λ-calculusas its functional core (e). A program (P) is a sequence of top-level operations (O) that is evaluated with relation to a runninginstance, enclosing state and code. We assume that a, b, c, . . . rangeover a set of names N , and that x, y, z, . . . range over a set ofvariables V . Names are globally visible in the application contextproviding a common namespace for all programming elements.Operations include the declaration/redefinition of state variables(var a = e) in the application name space, associating to namea, the value denoted by expression e. Another kind of operation isthe declaration/redefinition of pure data transformation elements(def a = e) which associates name a to the value denotedby expression e. Expressions defining names may use previouslydeclared names. Finally, operations of the form do e represent theexplicit execution of actions denoted by the expressions e.

The functional core (e) includes abstraction λx:τ.e and appli-cation e e′ following call-by-value evaluation. For the sake of sim-plicity we assume the usual sets of base values b (i.e. strings,integers, booleans, etc.) and corresponding binary operators (op),and the ternary conditional operator (?:). Names (a) in expressionsare implicitly coerced to their denotations in the application state.We extend the base λ-calculus with collections, with constructor[e1, . . . , en], and corresponding concatenation (@) and append (::)operations. The iterator iter(e, e′, x.y.e′′) denotes a fold-left op-eration on the collection denoted by expression e, and the iterated

expression e′′. Variable x denotes the current element in the col-lection, and variable y denotes either the value of expression e′′

in the previous iteration, or the initial value given by expressione′ in the first iteration. The destructor expression for collectionsmatch e with x::xs → e′ | [ ] → e′′ denotes one of two cases,depending on the value of expression e. In the case of a non-emptycollection, the evaluation proceeds with expression e′, where vari-able x denotes the head of the collection, and variable xs denotes itstail. In the case of an empty collection ([ ]), the result is denoted byexpression e′′. An expression action { a := e } value contains afinite sequence of delayed assignment statements to state variables.Note that a sequence of delayed statements may also be empty, inthat case we write, action { · }. In the example presented inSection 3 we have extended this base language with extra orthogo-nal constructs, such as records and let declarations. We also used alist comprehension query notation, similar to the one introduced byWadler [21]. List comprehension expressions can directly encodedin our core language in the usual way:

[ e | x← e′ ] , iter(e′, [ ], x.y.y@[e])

[ e | x← e′, f x ] , iter(e′, [ ], x.y.y@(f x ? [e] : [ ]))

4.1 Operational SemanticsWe define a reactive operational semantics by means of two layersof small-step reduction relations, one for program operations, andanother for λ-calculus expressions. The first layer is defined onprogram configurations (S;P;L), where S is a state mappingnames (a) to triples with the form (e, o, s), with e an expression,whose free names range over the domain of S, and o the currentdenotation of the name a, that can be either a computed value (v),or undefined (�). The set of names s, stores the names whosedefinition depend on a, and thus need to be updated when thedenotation of a changes. We call it the set of subscribers of a. Wewrite S[a 7→ (e, o, s)] to denote a state based on S where a isassociated with triple (e, o, s).

The runtime values are defined by the fragmentv ::= b | x | λx:τ.e | [v1, . . . , vn] | action { a := e }

that includes a set of base values (including true and false),variables, λ-abstractions, and collections of values. Expressions ofthe form action are also values, containing a sequence of delayedimperative statements. The evaluation of the enclosing expressions,and the execution of the assignment statements is only triggered atthe program level by a do operation. A program P in configuration(S;P;L), represents the sequence of top-level operations yet to beapplied to the running system, and queue L denotes the queue ofnames that are scheduled to be updated, i.e. whose value needs tobe propagated through the data-flow graph. We write [ ] to denotean empty queue, and use the notation L@L′ for concatenation, andconstructor a::L to denote a queue with head a and a tail L.

The reduction relation on program configurations, written(S;P;L) −→ (S ′;P ′;L′)

is defined by the rules in Figure 5. It is based on a reduction relationon expression configurations (S; e), written

S; e −→ e′

that specifies that expression e reduces to e′ with relation to a stateS. This reduction relation is defined by the rules shown in Figure 6.

Consider the following auxiliary abbreviations and definitionsused in the program reduction relation, and essential to understandthe rules in Figure 5.

Definition 1 (Subscribers of a Name). The set of subscribers ofname a, with relation to state S, written ψ(S, a), is defined by

ψ(S, a) ,

{s if S(a) = (e, o, s)∅ otherwise

4 2014/6/9

Page 5: Type-Safe Evolution of Data-Centric Applicationsmiguel.domingues.pt/docs/techreport-2014.pdf · Which means that applications may evolve without any service dis-ruption. We use a

s = ψ(S, a)

(S;var a = e,P; [ ]) −→ (S[a 7→ (e,�, s)];P; [a])(RVAR)

S′ = subscribe(S, a, e) s = ψ(S, a)

(S;def a = e,P; [ ]) −→ (S′[a 7→ (e,�, s)];P; [a])(RDEF)

(S[a 7→ (e′′, o, s)];doaction { a := e; a′ := e′ },P; [ ]) −→ (S[a 7→ (e,�, s)];doaction { a′ := e′ },P; [a]) (RASSIGN)

(S[a 7→ (e, o, s)];P; a::L) −→ (S[a 7→ (e, o, s)];P; a〈e〉::L) (RQEXP)

S; e −→ e′

(S;P; a〈e〉::L) −→ (S;P; a〈e′〉::L)(RQSTEP) (S[a 7→ (e, o, s)];P; a〈v〉::L) −→ (S[a 7→ (e, v, s)];P;L@s) (RQVAL)

S; e −→ e′

(S;do e,P; [ ]) −→ (S;do e′,P; [ ])(RDO) (S;doaction { · },P; [ ]) −→ (S;P; [ ]) (RSKIP)

Figure 5. Program Operational Semantics.

S; e −→ e′

S; E[e] −→ E[e′](RCONTEXT)

S(a) = (e, v, s)

S; a −→ v(RNAME)

v′′ = [[v op v′]]

S; v op v′ −→ v′′(ROP)

S; (λx.e) v −→ e{v/x} (RAPP) S; true ? e : e′ −→ e (RTRUE) S; false ? e : e′ −→ e′ (RFALSE)

S; iter([ ], v, x.y.e) −→ v (RNIL) S; iter(v::vs, v′, x.y.e) −→ iter(vs, e{v/x}{v′/y}, x.y.e) (RITERATE)

S; (match [ ] with x::xs→ e | [ ]→ e′) −→ e′ (REMPTY) S; (match v::vs with x::xs→ e | [ ]→ e′) −→ e{v/x}{vs/xs} (RMATCH)

Figure 6. Expression Operational Semantics.

Definition 2 (Free Names in Expressions). The set of free namesof expression e, written σ(e), is defined by

σ(a) , {a}σ(b) , ∅σ(x) , ∅σ(λx.e) , σ(e)

σ(e e′) , σ(e) ∪ σ(e′)σ(e op e′) , σ(e) ∪ σ(e′)σ(e ? e′ : e′′) , σ(e) ∪ σ(e′) ∪ σ(e′′)σ([e1, . . . , en]) , σ(e1) ∪ . . . ∪ σ(en)

σ(action { a := e }) , ∅σ(iter(e, e′, x.y.e′′)) , σ(e) ∪ σ(e′) ∪ σ(e′′)σ(match e with x::xs→ e′ | [ ]→ e′′), σ(e) ∪ σ(e′) ∪ σ(e′′)

Notice that the set of free names of imperative statements enclosedin action values is always empty. Since the set of free names is thebasic information used to build the data-flow graph, this expressesthe fact that changes are not propagated into action values, andthat their effects are not re-evaluated.

Definition 3 (Subscribe Function). The state, obtained from astate S, and updating the dependencies of a given name a, writtensubscribe(S, a, e), is defined by

subscribe(S, a, e) ,{b 7→ (e′, v, s ∪ {a}) | b ∈ σ(e) ∧ S(b) = (e′, v, s)}

∪ {b 7→ (e′, v, s \ {a}) | b 6∈ σ(e) ∧ S(b) = (e′, v, s)}

The reduction relation on program configurations (Figure 5)is designed to sequentially evaluate the operations in program P ,thus modifying state S and queue L accordingly. The generalidea behind a program configuration is to use the queue L toexpress the reactive semantics, and signal the situations where a

system reconfiguration can happen without disruption, i.e. wherenew operations can be evaluated. Rules RVAR, RDEF, and RASSIGN,deal with the three top-level operations, and their basic effect is tochange the definition of a given name in the state, and signal that itmust be re-evaluated by placing it in the (empty) queue. Rule RQEXPstarts the process of updating the value of name in the front of thequeue. This is accomplished by placing the associated expressionat the queue’s head (a〈e〉::L). Rule RQSTEP iteractively reduces theexpression at the head of the queue, by using the reduction relationfor expressions from Figure 6. Rule RQVAL updates the name athead of the queue with a computed value, and signals for the re-evaluation of all names whose definition depends on name a (i.e. itssubscribers) by appending s to queue L. Notice that var, def anddo operations only reduce in an empty queue, rules RVAR, RDEF,and RASSIGN.

Notice that in the case of a def operation, rule RDEF updatesthe initial state S so that all dependencies of a are refreshed (seeabove for the definition of subscribe(S, a, e)). In the case of a varoperation there is no need to update the state with new subscribers,since changes are not propagated into state variable definitions.

Rule RDO reduces the subexpression e, in an operation do e,to an action value. Rule RASSIGN processes one assignment at atime. The effect of an assignment is achieved by overwriting theexpression associated to the assigned name in the state, and byqueuing the name for evaluation. Finally, rule RSKIP ignores theempty action value, and continues the execution of the remainingoperations in P .

Our program operational semantics defines a data-driven (push)approach, in opposition to a pull approach of other reactive lan-guages [12]. This results in the immediate propagation of changesthrough the dependency graph, until reaching an empty queue. In

5 2014/6/9

Page 6: Type-Safe Evolution of Data-Centric Applicationsmiguel.domingues.pt/docs/techreport-2014.pdf · Which means that applications may evolve without any service dis-ruption. We use a

(VAR)Γ; δ ` e : τ a 6∈ dom(Γ) a 6∈ uΓ(δ) Γ, a : varδ(τ) ` P

Γ ` var a = e,P

(DEF)Γ; δ ` e : τ a 6∈ dom(Γ) a 6∈ uΓ(δ) Γ, a : defδ(τ) ` P

Γ ` def a = e,P

Γ; δ ` e : Action Γ ` PΓ ` do e,P

(DO)

Figure 7. Typing Rules for Programs.

Section 4.2 we present a type system that establishes enough con-ditions so that we can prove convergence of the propagation pro-cess (see Section 6). A halting configuration is reached when nooperation is available and the queue is empty, i.e. it is of the form(S; ·; [ ]).

We next present the reduction relation on expressions, definedby the rules in Figure 6, based on a standard notion of evaluationcontexts (E) with rule RCONTEXT specifying the expression reduc-tion in a context.

Definition 4 (Expressions Contexts). Evaluation contexts for ex-pressions, E , are defined by

E ::= E op e | v op E| E e | (λx.e) E| E ? e : e′

| [v1, . . . , vi, E, ei+2, . . . , en]| iter(E, e, x.y.e′) | iter(v, E, x.y.e)| match E with x::xs→ e | [ ]→ e′

Rule RNAME specifies the implicit dereference of a name, re-ducing it to the corresponding value in state S. Reduction of binaryoperations (ROP) is abstracted from the system, and rule RAPP im-plements the usual reduction of a call-by-value application. Theternary conditional operator (RTRUE and RFALSE) also follows theusual semantics. The semantics of collection iteration (RNIL andRITERATE), and collection destruction (REMPTY and RMATCH) alsofollow straightforward semantics.

4.2 Type SystemOur type language comprises a representative for basic types β(e.g. Bool, Int), function types τ → τ ′, types for homogeneouscollections (τ∗), and type Action for action values.

τ ::= β | τ → τ ′ | τ∗ | Action

The typing relation on programs is defined by a set of rules, shownin Figure 7, which directly depends on the typing relation on ex-pressions and statements, in Figure 8. Both typing judgments aredefined with relation to typing environments Γ, that are mappingsfrom variables to types, and names to special type annotations.Type annotations for names are designed to carry extra informa-tion about names, and are either of the form defδ(τ) or varδ(τ).In both cases, δ is a set of names containing all name dependen-cies of the expression associated to the annotated name. This setbecomes essential to avoid cyclic definitions, which would causeinfinite loops during propagation of changes, and also allows tostatically discipline the redefinition of names.

The typing relation of programs is defined by a judgment of theform Γ ` P , and is inductively defined by the rules in Figure 7.The typing of expressions has the judgment of the form Γ; δ `e : τ , which asserts that expression e has type τ with relationto the typing environment Γ. An invariant of this judgment isthat expression e uses, at most, the set of names δ, with δ ⊆dom(Γ). Finally, the typing of assignments is kept separate, with

the judgment Γ; δ ` a := e, that asserts that the assignment a := eis well-typed with relation to the typing environment Γ, and uses,at most, the set of names δ. This judgment is kept separate for thesake of simplicity and extensibility of the type system with otherimperative operations. The rules for expressions and statements arepresented in Figure 8.

The typing rules for programs, in Figure 7, follow the generalstructure of sequentially examining the top-level operations in aprogram. The conditions to define new names are the same forstate variables (VAR) and for data transformation expressions (DEF).At this stage we require that the declared name (a) is fresh inthe typing environment (a 6∈ dom(Γ)). This statically disallowsthe redefinition of names, which are covered in Section 5.1 by anextended version of the type system. The condition a 6∈ uΓ(δ)considers all the names used in expression e, and its expansionwith relation to the typing environment as defined below. Thisstatically ensures that the declared name is not transitively usedin the expression e.

Definition 5 (Extended Dependencies). The extended dependen-cies of a set of names δ, with relation to a typing environment Γ,written uΓ(δ), is defined by:

uΓ(δ) , δ ∪⋃a∈δ

{ uΓ(δ′) | Γ(a) = defδ′(τ)}

Computing the extended set of name dependencies is essential tostatically avoid circular dependencies, and ensuring the conver-gence of the propagation of changes. Notice that the dependenciesof the state variables in δ are not expanded. Thus, they are not ac-counted for in the cycle detection condition. This is sound because,at runtime, changes are not propagated into the definitions of statevariables. Recall that the initializer expressions of state variablesare only evaluated once. Our formal results include a relation be-tween a well-typed state and well-formed extended dependency set(see Appendix B). The typing of top-level operations of the formdo e, covered by rule DO, just requires that expression e is typedwith type Action. Notice that the dependencies of e (δ) are ignoredin the bookkeeping process. This is sound given that the effect ofan action is never re-executed by the propagation of changes.

The typing relation on expressions, in Figure 8, follows stan-dard lines and is extended so that name dependencies (δ) are con-servatively computed. The most interesting cases are the axioms fornames (DNAME and VNAME), where resulting dependencies must in-clude the name itself, and rule for assignment statements (ASSIGN)that requires the assigned name to be included in the dependencies.In all other cases, dependencies are simply propagated through thederivation.

5. Dynamic ReconfigurationIn this section we extend our language to support the dynamic re-configuration. We propose a uniform mechanism that allows for theexisting operations to redefine names, and extend our type systemto ensure that all reconfigurations are sound. Consider the exam-ple from Section 3, which started with a simple data model andfunctionality, and we now want to evolve to meet a new require-ment, that is to store which users have “liked” each message, in-stead of simply counting occurrences. In our dynamic reconfigura-tion model, it is possible to incrementally reconfigure the existingsystem. Figure 9 depicts the sequence of operations that are neededto meet this new requirement.

We start by creating a new state variable (whoLikes) to store therelation between messages and users. Note that, in this case, therewas no previous information of which user liked each message, andfor the sake of simplicity, we instantiate the state variable with onlyone record stating that user “Henry” “liked” the message with id 0.

6 2014/6/9

Page 7: Type-Safe Evolution of Data-Centric Applicationsmiguel.domingues.pt/docs/techreport-2014.pdf · Which means that applications may evolve without any service dis-ruption. We use a

(DNAME)Γ, a : defδ′ (τ); δ ∪ {a} ` a : τ

(VNAME)Γ, a : varδ′ (τ); δ ∪ {a} ` a : τ

(ID)Γ, x : τ ; δ ` x : τ

(VALUE)Γ; δ ` b : β

Γ; δ ` e : Bool Γ; δ ` e′ : τ Γ; δ ` e′′ : τ

Γ; δ ` e ? e′ : e′′ : τ(IF)

Γ, x : τ ; δ ` e : τ ′

Γ; δ ` λx:τ.e : τ → τ ′(ABS)

Γ; δ ` e : τ → τ ′ Γ; δ ` e′ : τ

Γ; δ ` e e′ : τ ′(APP)

Γ; δ ` e : τ Γ; δ ` e′ : τ ′ op: τ → τ ′ → τ ′′

Γ; δ ` e op e′ : τ ′′(OP)

Γ; δ ` e : τ∗ Γ; δ ` e′ : τ ′ Γ, x : τ, y : τ ′; δ ` e′′ : τ ′

Γ; δ ` iter(e, e′, x.y.e′′) : τ ′(ITER)

Γ; δ ` e : τ∗ Γ, x : τ, xs : τ∗; δ ` e′ : τ ′ Γ; δ ` e′′ : τ ′

Γ; δ `match e with x::xs→ e′ | [ ]→ e′′ : τ ′(MATCH)

Γ; δ ` ei : τ

Γ; δ ` [e1, . . . , en] : τ∗(COLLECTION)

Γ; δ ` ai := ei

Γ; δ ` action { a := e } : Action(ACTION)

Γ, a : varδ′ (τ); δ ` e : τ

Γ, a : varδ′ (τ); δ ∪ {a} ` a := e(ASSIGN)

Figure 8. Typing Rules for Expressions and Assignments.

varwhoLikes =

{name : “Henry”,msgId : 0

}::[ ]

varmsgText = [

id : m.id,author : m.author,message : m.message

| m← messages ]

def new = λa.λm.action {msgText := msgText@[

id : size,author : a,message : m

] }

def like = λid.action { whoLikes := whoLikes@[

{name : user,msgId : id

}] }

def countLikes = λid.iter(whoLikes, 0, x.y.(x.msgId = id ? (y + 1) : y))

def messages = [

id : m.id,author : m.author,message : m.message,likes : countLikes m.id

| m← msgText ]

Figure 9. Bulletin Board Reconfiguration.

Next, we create a new collection of messages, based on the existingcollection messages, but containing only the fields id, author, andmessage. This collection is stored in a new state variable msgText.Given the reconfigured persistent state, we now redefine the neces-sary existing names to reach our goal. Function new is modified,so to add messages to msgText instead of messages. Function likeis also redefined in such a way, that it appends a new record to thewhoLikes collection, instead of messages. We declare an auxiliaryname countLikes that, for a given message identifier id returns thenumber of “likes” for that particular message, by iterating over thecollection whoLikes and counting the occurrences with an equalmessage identifier. Finally, name messages is redefined to point tothe newly defined state variables msgText and whoLikes. Noticethat name messages now conceptually represents a view, with es-sentially the same information as before, obtained from state vari-ables msgText and whoLikes (indirectly through countLikes). Allthese reconfiguration steps are performed incrementally, and seam-lessly with relation to the elements used in the user interface inFigure 3 (wall and post), that remain unchanged and operating asbefore.

Our dynamic reconfiguration model enables an incremental andlive programming style of applications, without disrupting opera-tion and consistency of code and data. Interferences due to dataduplication can, and should, be questioned in intermediate states of

the reconfiguration. That problem is out of the scope of this paper,and should be addressed in future work, by means of orthogonalcontrol mechanisms.

5.1 Typing Name RedefinitionWe now describe the extension of our programming language tosupport the incremental reconfiguration of systems. Notice thatthe operational semantics already defined, in Section 4.1, alreadysupports the redefinition of state variables and data transformationexpressions. So, the proposed extension is defined at the type level,in order to disallow sequences of redefinitions that are not sound.

The typing rules introduced, in Section 4.2, require that typename definitions do not support any form of redefinition. Therefore,we present in Figure 10, additional rules that allow and disciplineit. We divide the redefinition of programming elements (var anddef ) into three different cases.

In the first case, rules UVAR and UDEF, type the redefinition ofa name, by allowing a different expression while maintaining thesame type. These rules extend the ones presented in Section 4.2 bychecking that the type is maintained, and that the old dependencies(δ′) registered in Γ are replaced by the new dependencies (δ),given by the typing of expression e. We prove that this is enoughinformation to continue avoiding circular name dependencies. We

7 2014/6/9

Page 8: Type-Safe Evolution of Data-Centric Applicationsmiguel.domingues.pt/docs/techreport-2014.pdf · Which means that applications may evolve without any service dis-ruption. We use a

Γ; δ ` e : τ a 6∈ uΓ(δ) Γ, a : varδ(τ) ` PΓ, a : varδ′ (τ) ` var a = e,P

(UVAR)Γ; δ ` e : τ a 6∈ uΓ(δ) τ 6= τ ′ a 6∈ ρ(Γ) Γ, a : varδ(τ) ` P

Γ, a : varδ′ (τ′) ` var a = e,P

(UVART)

Γ; δ ` e : τ a 6∈ uΓ(δ) Γ, a : defδ(τ) ` PΓ, a : defδ′ (τ) ` def a = e,P

(UDEF)Γ; δ ` e : τ a 6∈ uΓ(δ) τ 6= τ ′ a 6∈ ρ(Γ) Γ, a : defδ(τ) ` P

Γ, a : defδ′ (τ′) ` def a = e,P

(UDEFT)

Γ; δ ` e : τ a 6∈ uΓ(δ) Γ, a : defδ(τ) ` PΓ, a : varδ′ (τ) ` def a = e,P

(VARDEF)

Figure 10. Typing Rules for Program Reconfiguration.

also show that, since the type is not modified, all expressions in thestate are still sound.

The second case is covered by rules UVART and UDEFT, that typethe reconfiguration of a name using an expression of a differenttype. Both rules ensure that a name can change type only if noother name is using it. This is ensured by the condition a 6∈ ρ(Γ),where ρ(Γ) stands for the union of all dependencies sets in Γ.

Definition 6 (Union of Name Dependencies). The union of thename dependencies sets, in a given a typing environment Γ, writtenρ(Γ), is defined by

ρ(Γ) ,⋃

a∈dom(Γ)

{ δ | Γ(a) = varδ(τ) ∨ Γ(a) = defδ(τ)}

With this extra condition, we disallow the redefinition of namethat is being used elsewhere in the system. Reconfigurations, thatchange type specification, are possible through sequences of recon-figuration operations that are performed in such an order that nobroken dependencies ever exist in the application.

Finally, the third allowed case, is expressed by rule VARDEF,where there is a modification from a state variable to a pure datatransformation element. For the sake of simplicity we disallow thedual case, which would require recomputing of all name dependen-cies in Γ.

In summary, reconfiguration is supported in a disciplined andordered way. If maintaining the type, cycles are still detected. And,if the type is modified then a specific order must be followed toensure that no definition is broken.

6. Type SafetyThe soundness results for our language are based on proving typesafety and change propagation convergence, which we derive fromstandard subject reduction theorems. Beside the usual type errors,our type system also ensures that the intended (reactive) behavioris kept sound even when the system is reconfigured. We have lim-ited the expressiveness of the functional core to be able to formallyestablish the termination of the propagation process. Nevertheless,the language can be orthogonally extended to include general recur-sion. The results presented here follow a syntactic approach [24],and are proved by induction on the length of the typing derivations.We provide proof sketches for most results, whereas the full proofscan be found in Appendix B. All results are based on the typingof runtime program configurations, which in turn relies on a well-formed relation on queues, and well-typed relations on states andprograms.

The notion of well-formed queue (Definition 7) with relationto a state and typing environment, written S; Γ ` L, asserts thatthe partial order imposed by the subscribers relation in S is well-founded. We establish that the empty queue is always reachablefrom queue L, through the subscriber relation. Also, when a queueis of the form a〈e〉::L, we establish that expression e has the same

type according to the type annotation of a in the typing environmentΓ. We prove that S; Γ ` L is an invariant of the reduction relation,and conclude that the update process converges (see Appendix B).

Definition 7 (Well-Formed Queue). A queue L is well-formed withrelation to a state S and a typing environment Γ, written S; Γ ` L,if it can be inductively defined by the rules

S; Γ ` [ ]s = ψ(S, a) S; Γ ` L@s

S; Γ ` a::L

Γ; δ ` e : τ S; Γ, a : defδ(τ) ` a::LS; Γ, a : defδ(τ) ` a〈e〉::L

Γ; δ ` e : τ S; Γ, a : varδ(τ) ` a::LS; Γ, a : varδ(τ) ` a〈e〉::L

The typing judgment for states (Definition 9), written Γ | Γ′ `S, asserts that the names in state S and its subscribers form a well-founded partial order in Γ′, and all expressions contained in S arewell-typed with relation to the typing environment Γ,Γ′. The typ-ing relation imposes the disjointness of dom(S) and dom(Γ), andalso a well-founded order on names, through name dependency re-lation contained in typing environment Γ, in a structure resemblingthe ordered logic approach [16]. This separation of the typing en-vironment (Γ and Γ′) establishes the absence of circular dependen-cies, since subscribers (s) are on one side, and name dependencies(δ) on the other side. On the one hand, the expression associated toa name in state S is only dependent on names from the typing envi-ronment Γ, i.e.uΓ(δ) ⊆ dom(Γ). On the other hand, a name is onlyused by expressions associated to names on Γ′, tS(s) ⊆ dom(Γ′),where tS(s) is the expansion of the subscribers relation in S (Defi-nition 8). From these invariant conditions, we conclude that for anyname a in a well-typed state S, the singleton queue [a] is alwayswell-formed, S, a 7→ (e, o, s); Γ′ ` [a]. Note that the names re-maining in S are the same names remaining in Γ′ (both domainsare equal).

Definition 8 (Expansion of Subscribers). The expansion of sub-scribers relation, written tS(s), for a set of names s, with relationto a typing environment S, is defined by

tS(s) , s ∪⋃a∈s

{ tS(s′) | s′ = ψ(S, a)}

Definition 9 (Well-Typed State). A state S is well-typed withrelation to two typing environments Γ′ and Γ′′ with dom(Γ′) ∩dom(Γ′′) = ∅, if Γ′ | Γ′′ ` S can be inductively defined by therules in Figure 11.

We next introduce the notion of well-typed program configu-ration (Definition 10), which relies on the previous definitions ofwell-typed state (Definition 9), well-typed program (presented inSection 4.2), and well-formed queue (Definition 7).

Definition 10 (Well-Typed Program Configuration). A programconfiguration, written (S;P;L), is well-typed with relation to a

8 2014/6/9

Page 9: Type-Safe Evolution of Data-Centric Applicationsmiguel.domingues.pt/docs/techreport-2014.pdf · Which means that applications may evolve without any service dis-ruption. We use a

Γ | · ` ·

Γ; δ ` e : τ Γ; δ ` v : τ Γ, a : defδ(τ) | Γ′ ` S S, a 7→ (e, v, s); Γ ` [a] uΓ (δ) ⊆ dom(Γ) tS (s) ⊆ dom(Γ′)

Γ | a : defδ(τ),Γ′ ` S, a 7→ (e, v, s)

Γ; δ ` e : τ Γ, a : defδ(τ) | Γ′ ` S S, a 7→ (e,�, s); Γ ` [a] uΓ (δ) ⊆ dom(Γ) tS (s) ⊆ dom(Γ′)

Γ | a : defδ(τ),Γ′ ` S, a 7→ (e,�, s)

Γ, a : varδ(τ),Γ′; δ ` v : τ Γ, a : varδ(τ) | Γ′ ` S S, a 7→ (e, v, s); Γ ` [a] tS (s) ⊆ dom(Γ′)

Γ | a : varδ(τ),Γ′ ` S, a 7→ (e, v, s)

Γ,Γ′; δ ` e : τ Γ, a : varδ(τ) | Γ′ ` S S, a 7→ (e,�, s); Γ ` [a] tS (s) ⊆ dom(Γ′)

Γ | a : varδ(τ),Γ′ ` S, a 7→ (e,�, s)

Figure 11. Well-Typed State.

typing environment Γ, if Γ ` (S;P;L) is derivable by the follow-ing rule

· | Γ ` S Γ ` P S; Γ ` LΓ ` (S;P;L)

We also define a well-typed expression configuration (Def-inition 11), relying on the previous definitions of well-typedstate (Definition 9), and well-typed expression (presented in Sec-tion 4.2).

Definition 11 (Well-Typed Expression Configuration). An expres-sion configuration, written (S; e), is well-typed with relation to atyping environment Γ, if Γ ` (S; e) is derivable by the followingrule

· | Γ ` S Γ; δ ` e : τ

Γ ` (S; e)

Based on these auxiliary definitions, we establish type safetyand present here the main results for programs: progress (The-orem 1), type preservation (Theorem 2) and queue convergence(Theorem 3). These results are based on intermediate results forexpressions, states, and queues. For full details and proofs, pleaserefer to Appendix B.

To establish progress of programs (Theorem 1), we need toensure a stronger invariant of the reduction relation, that says thatno names can be undefined (�), except perhaps for the namecurrently being evaluated, i.e. if there is an undefined value in thestate, it corresponds to the name which is the only element in theevaluation queue.

Theorem 1 (Progress of Programs). For all program configura-tions (S;P;L) if Γ ` (S;P;L) and ∀a ∈ dom(S). (S(a) =(e,�, s) ⇒ L = [a]), then there is a program configuration(S ′;P ′;L′) such that (S;P;L) −→ (S ′;P ′;L′) and ∀a ∈dom(S ′). (S ′(a) = (e,�, s)⇒ L′ = [a]).

Type preservation for programs (Theorem 2) follows standardlines, and is proven by induction on the derivation of (S;P;L) −→(S ′;P ′;L′). We prove for all possible program reductions, withmost cases using the definitions of well-typed program config-uration and state. The most involved cases are for RDEF, RVAR,which involve an inversion property in the typing of states, andRQVAL, where we need to consider the cases of top-level definitionsand variables, and carefully reconstruct well-typed states and well-formed queues.

Theorem 2 (Programs Type Preservation). For all configurations(S;P;L) and (S ′;P ′;L′), and typing environments Γ, if Γ `(S;P;L) and (S;P;L) −→ (S ′;P ′;L′) then, there is a typingenvironment Γ′, such that Γ′ ` (S ′,P ′,L′).

In order to prove the convergence of the evaluation queue, weintroduce a measure on names (Definition 12) corresponding to thenumber of all names that must be refreshed on update. In this waywe can prove that our measure always decreases during evaluation,and that well-typed program configurations always reach an emptyqueue.

Definition 12 (Name Length). We define the length of a name awith relation to a state S, written mS (a), by:

mS (a) , 1 +∑

si∈ψ(S,a)

mS (si)

Similarly, we define the length of a queue L with relation to astate S, written mS (L), as the sum of the lengths of all its names(Definition 13).

Definition 13 (Queue Length). We define the length of a queue Lwith relation to a state S, written, mS (L), as follows:

mS (L) ,

{0 if L = [ ]1 +mS (a) +mS (L′) if L = a::L′mS (a) +mS (L′) if L = a〈e〉::L′

Intuitively, the length of a name represents the number of computa-tional steps needed to propagate an update through the name depen-dencies graph. The length of a queue, represents the computationsteps needed to reach an empty queue.

We now need to relate the typing relation of program config-urations, and the definition of the length function for a particularqueue. This results in a lemma (Lemma 1) establishing that a non-empty queue decreases in length after a finite number of reductionsteps.

Lemma 1 (Queue Convergence). For all configurations (S;P;L)and (S ′;P ′;L′), and typing environments Γ, if Γ ` (S;P;L) andL 6= [ ] then (S;P;L) −→∗ (S ′;P ′;L′) and mS (L′) < mS (L).

Based on this previous result, we can now establish a strongerresult (Theorem 3) where a well-typed program configuration witha non-empty queue, reaches a program configuration with an emptyqueue after a finite number of steps.

Theorem 3 (Convergence). For all configurations (S;P;L) and(S ′;P ′; [ ]), and typing environments Γ, if Γ ` (S;P;L) then(S;P;L) −→∗ (S ′;P ′; [ ]).

In summary, the main results we extract from the operationalsemantics and type system are type safety of programs (Theorem 1and Theorem 2), and convergence of the change propagation (Theo-rem 3). These results allow us to ensure that the automatic propaga-tion of changes caused by the execution of imperative assignments

9 2014/6/9

Page 10: Type-Safe Evolution of Data-Centric Applicationsmiguel.domingues.pt/docs/techreport-2014.pdf · Which means that applications may evolve without any service dis-ruption. We use a

def noFilter = λm.true

var currentFilter = noFilter

def filteredMessages = [m | m← messages, currentFilter m ]

def authorFilter = λa.λm.(m.author = a)

def wall = [

{message : m,incLikes : like m.id

}| m← filteredMessages ]

Figure 12. Message Filters Code.

happens without causing infinite propagation loops, and dynamicreconfiguration of both code and data does not break type safety.

7. Extending Our ExampleIn this section we extend our bulletin board application previouslyintroduced in Section 3. This extension adds a filtering mechanismthat allows to show only the messages of a given user, e.g. by click-ing on the user’s name in the UI (Figure 13(a)) would display onlythe messages from that user (Figure 13(b)). Notice that this exten-sion may be applied after or before the reconfiguration introducedin Section 5 (Figure 9), obtaining the same final application.

Consider the code depicted in Figure 12. We start by creat-ing the noFilter name, that is one of our filters. In this case, itacts like “show all” filter. We use the state variable currentFilterto hold the filter currently applied to the list. This allows us tomodify the active filter with the execution of an action. NamefilteredMessages iterates over the messages collection, filtering themessages according to the active filter (currentFilter). Notice thatthis new name, has the same behavior as name messages definedin Figure 2 and then redefined in Figure 9. At this point, none ofthe messages is filtered, since the active filter corresponds to thenoFilter, which returns true for any given message m. This re-sults in a list of filtered messages containing all the messages. Toachieve our goal of filtering messages by author we define nameauthorFilter. We also reconfigure our application by redefiningname wall to use the filteredMessages list, instead of messages.Hence, this reconfiguration displays messages according to the ac-tive filter (currentfilter).

In Figure 13 we show the possible states of the active filter. Byclicking on the author’s name associated to each message, the activefilter changes, and so does the list of messages shown. For instance,clicking on “Paul” corresponds to the execution of

doaction { currentFilter := authorFilter “Paul” }By execution this action, currentFilter changes, which causes apropagation to happen and changes in name wall, now containingthe two messages whose author is “Paul” (Figure 13(b)).

Notice that name filteredMessages is automatically changedwhen collection messages, is changed. For instance, such reactivebehavior will occur when a new message is added:

do (new “Paul” “I’ll pick you up at 6.”)

Name wall is reactively updated displaying also this new mes-sage. Clicking the “Clear filter” button (Figure 13(b)) would simplychange the active filter, corresponding to the execution of the fol-lowing operation:

doaction { currentFilter := noFilter }Any modification to the application state (e.g. add a message,changing the active filter) causes a propagation of changes in theapplication, refreshing the displayed messages in the user interface.

With this small extension we show how the dynamic reconfigura-tion mechanism of our language enables the type-safe constructionand maintenance of data-centric applications, while enabling a re-active behavior that allows to keep all named elements always up-to-date with respect to the application persistent state. We also il-lustrate how user interface elements such as buttons or links actionscan be mapped to an action execution.

8. Related WorkData-flow programming languages have been extensively studiedin the past and summarized in surveys [12]. The pure data-flowmodel considers that every node is pure and without side effects.Likewise, our definition of a data-flow graph, obtained from all top-level operations, def or var, is built out of effect-free expressions.Imperative features are kept apart from the data-flow propagationmechanism. Many data-flow programming languages also exploreparallel computation by computing several non-interfering nodessimultaneously. We focus on the core reconfiguration model, andwe believe that such concerns, although interesting, are orthogo-nal. The support to parallel propagation can be achieved with anexecution queue, sensitive to data dependencies.

Adaptive Functional Programming [1] uses an underlying de-pendency graph and a change propagation algorithm to adapt toinput changes. The change propagation algorithm is encoded intotraces in the operational semantics. We encode a similar propaga-tion mechanism into our operational semantics, by means of theevaluation queue. Our approach, although inspired in some aspectson AFP, focuses on providing a terminating reactive framework thatcan be dynamically changed.

FrTime [7] is another approach for writing functional reactiveapplications. Reactivity is embedded into a call-by-value dynamicprogramming language. In principle, our language can be encodedinto the FrTime’s reactive framework, where cells play the role ofstate variables (var), pure data transformation elements (def ) canbe mapped to computations over signals, and execution (do) of ac-tions can be encoded to the set-cell! operator in FrTime. How-ever, our approach goes beyond that point, by statically verifyingprograms, to ensure convergence of change propagation, and alsothe safety of reconfigurations. Unlike our language, FrTime allowsthat a cyclic, unguarded, definition is added to the system, causingit to diverge.

Reactive systems [9, 14, 15, 17] maintain an ongoing interac-tion with their environment, and are based on the notions of in-stants (when a system reacts) and activations (what causes a re-action). In our language, activations correspond to the executionof actions, causing the system to react. Our incremental style ofprogramming also maintains an ongoing interaction with the en-vironment, where reconfigurations can be issued, or actions can beexecuted to change the application persistent state. Imperative reac-tive languages [3, 4, 10] usually require programs to be developedwith special and explicit constructs to enable reactivity. FunctionalReactive Programming is also an area where several approacheshave been proposed [14, 17, 22, 23]. However, neither of these ap-proaches combines reactivity with a statically verified dynamic re-configuration mechanism as the one presented in this paper.

TouchDevelop [5] provides a programming environment withimmediate feedback in the development of user interfaces. It pro-vides a statically verified approach by means of a type and effectsystem, that separates presentation and application code. The edit-compile-run development cycle is tightened by allowing the displaycode to be refreshed without restarting programs. Our approachprovides a more uniform programming mechanism that also allowsthe evolution of complete programs without the need to recompileor restart it.

10 2014/6/9

Page 11: Type-Safe Evolution of Data-Centric Applicationsmiguel.domingues.pt/docs/techreport-2014.pdf · Which means that applications may evolve without any service dis-ruption. We use a

7:11 PM

PaulHi there! wanna go out tonight?

HenryCool! Where to?

10

0

I’ll pick you up at 6.

Post message Clear filter

MaryLet’s go to the movies!

PaulGreat idea, Startrek is on again!

3

8

(a)

7:11 PM

PaulHi there! wanna go out tonight?

PaulGreat idea, Startrek is on again!

10

8

I’ll pick you up at 6.

Post message Clear filter

(b)

doaction { currentFilter := authorFilter “Paul” }

doaction { currentFilter := noFilter }

Figure 13. Bulletin Board with Filters UI Mockup.

Several works on dynamic reconfiguration and incrementalcomputation have already been proposed [8, 11, 20], and are mostlydesigned for imperative programming languages. For instance [11]provides dynamic updates in programs by explicitly defining log-ical regions where updates may occur. When the execution of aprogram reaches an update region, if a dynamic update is availableat that point in the execution, it is applied. Up to some point, ourapproach is similar. We do not explicitly define update regions orexecution points, but we interpolate reconfiguration actions witheach update cycle of the system. By combining reactivity with dy-namic reconfiguration we are able to maintain a name dependencygraph that changes dynamically, while maintaining the typing in-variants. To the best of our knowledge, this paper presents the firstwork that supports dynamic reconfiguration in reactive and imper-ative programming languages.

9. Final RemarksWe have presented the syntax, operational semantics and type sys-tem for a core reactive and imperative programming language, thatsupports dynamic reconfiguration of both code and data. We havealso stated provable type preservation and progress theorems forprograms, including a queue convergence result. Besides support-ing dynamic reconfiguration, our operational semantics also sup-ports reactivity by propagating changes through a name dependen-cies graph. This means that visible names, are always up-to-datewith respect to the persistent state of the application. Our type sys-tem statically ensures that both data propagation and reconfigura-tion happens without breaking type safety.

We believe that this is a suitable core model, at the right ab-straction level, for an agile development tool that assists on the de-velopment of data-centric reactive applications requiring constantevolution. We can expect high productivity gains provided by sucha programming environment that, at each construction step and re-configuration action, ensures the consistency of code and underly-ing data, and provides constant feedback about the new added dataand behavior. Our future roadmap includes extensions related to

control sharing to support collaborative developments. Other inter-esting features involve parallelization of the queue based on sepa-ration properties, and the obvious optimizations of avoiding unnec-essary computations.

References[1] U. A. Acar, G. E. Blelloch, and R. Harper. Adaptive Functional

Programming. ACM Transactions on Programming Languages andSystems, 28(6), 2006.

[2] P. Bhattacharya and I. Neamtiu. Dynamic Updates for Web and CloudApplications. In Proceedings of APLWACA, 2010.

[3] F. Boussinot. Reactive C: an extension of C to program reactivesystems. Software: Practice and Experience, 21(4), 1991.

[4] F. Boussinot and J.-F. Susini. The SugarCubes tool box: a reactiveJava framework. Software: Practice and Experience, 28(14), 1998.

[5] S. Burckhardt, M. Fahndrich, P. de Halleux, S. McDirmid, M. Moskal,N. Tillmann, and J. Kato. It’s Alive! Continuous Feedback in UIProgramming. In Proceedings of Programming Language Design andImplementation, 2013.

[6] Y. Chen, J. Dunfield, and U. A. Acar. Type-directed automatic incre-mentalization. In Proceedings of Programming Language Design andImplementation, 2012.

[7] G. H. Cooper and S. Krishnamurthi. Embedding dynamic dataflow ina call-by-value language. In Proceedings of ESOP, 2006.

[8] D. Duggan. Type-based hot swapping of running modules. ActaInformatica, 41(4), 2005.

[9] N. Halbwachs. Synchronous Programming of Reactive Systems. InProceedings of Computer Aided Verification, 1998.

[10] M. A. Hammer, U. A. Acar, and Y. Chen. CEAL: a C-based languagefor self-adjusting computation. In Proceedings of PLDI, 2009.

[11] M. Hicks and S. Nettles. Dynamic Software updating. ACM Transac-tions on Programming Languages and Systems, 27(6), 2005.

[12] W. M. Johnston, J. R. P. Hanna, and R. J. Millar. Advances in DataflowProgramming Languages. ACM Computing Surveys, 36(1), Mar. 2004.

[13] D.-Y. Lin and I. Neamtiu. Collateral Evolution of Applications andDatabases. In Proceedings of IWPSE-Evol, 2009.

11 2014/6/9

Page 12: Type-Safe Evolution of Data-Centric Applicationsmiguel.domingues.pt/docs/techreport-2014.pdf · Which means that applications may evolve without any service dis-ruption. We use a

[14] L. Mandel and M. Pouzet. ReactiveML: a reactive extension to ML. InProceedings of Principles and Practice of Declarative Programming,2005.

[15] H. Nilsson, A. Courtney, and J. Peterson. Functional Reactive Pro-gramming, Continued. In Proceedings of Workshop on Haskell, 2002.

[16] F. Pfenning and R. J. Simmons. Substructural Operational Semanticsas Ordered Logic Programming. In Proceedings of Logic In ComputerScience, 2009.

[17] R. R. Pucella. Reactive Programming in Standard ML. In Proceedingsof Conference on Computer Languages, 1998.

[18] G. Ramalingam and T. Reps. A categorized bibliography on incre-mental computation. In Proceedings of Principles of ProgrammingLanguages, 1993.

[19] P. Sewell. Modules, abstract types, and distributed versioning. InProceedings of Principles of Programming Languages, 2001.

[20] G. Stoyle, M. Hicks, G. Bierman, P. Sewell, and I. Neamtiu. MutatisMutandis: Safe and Predictable Dynamic Software Updating. ACMTOPLAS, 29(4), 2007.

[21] P. Wadler. Comprehending Monads. In Proceedings of LISP andFunctional Programming, 1990.

[22] Z. Wan and P. Hudak. Functional reactive programming from firstprinciples. In Proceedings of Programming Language Design andImplementation, 2000.

[23] Z. Wan, W. Taha, and P. Hudak. Real-time FRP. In Proceedings ofInternational Conference on Functional Programming, 2001.

[24] A. Wright and M. Felleisen. A syntactic approach to type soundness.Information and Computation, 115(1), 1994.

[25] D. Yellin and R. Strom. INC: a language for incremental computa-tions. In Proceedings of Programming Language Design and Imple-mentation, 1988.

12 2014/6/9

Page 13: Type-Safe Evolution of Data-Centric Applicationsmiguel.domingues.pt/docs/techreport-2014.pdf · Which means that applications may evolve without any service dis-ruption. We use a

A. Extra DefinitionsDefinition 14 (Substitution). Given an expression e, a value v and a variable x, the substitution relationfor expression, written e{v/x}, replaces all occurrences of x by the value v in e. We define the substitutionrelation for expressions inductively, as follows

x{v/x} , v x 6= y

y{v/x} , y

a{v/x} , a

(action { a := e }){v/x} , action { a := e{v/x} }

(λx.e){v/y} , λx.(e{v/y}) x 6= y

v{x/v′} , v v 6= λx.e ∧ v 6= action { a := e }

(e f){v/x} , (e{v/x}) (f{v/x})

(e op f){v/x} , (e{v/x}) op (f{v/x})

(e ? e′ : e′′){v/x} , (e{v/x}) ? (e′{v/x}) : (e′′{v/x})

[e1, . . . , en]{v/x} , [e1{v/x}, . . . , en{v/x}]

(iter(e, f, x.y.g)){v/z} , iter(e{v/z}, f{v/z}, x.y.g{v/z}) z 6= x ∧ z 6= y(match e withy::ys→ f : g

){v/x} ,

(match e{v/x} withy::ys→ (f{v/x}) : (g{v/x})

)x 6= y

13 2014/6/9

Page 14: Type-Safe Evolution of Data-Centric Applicationsmiguel.domingues.pt/docs/techreport-2014.pdf · Which means that applications may evolve without any service dis-ruption. We use a

B. ProofsLemma 2 (Substitution for Expressions). For all expression configurations e and typing environments Γ, ifΓ, x : τ ′; δ ` e : τ and a value v such that Γ; δ ` v : τ ′, then Γ; δ ` e{v/x} : τ .

Proof. By induction on the size of the typing derivation and analyzing the last case applied.1. Base Value

(H1) Γ, x : τ ′; δ ` b′ : τ(H2) Γ; δ ` v : τ ′

(3) b′{b/x} = b′ by Definition 14? Γ; δ ` v′ : τ from (H1, 3)

2. Variable Substitution(H1) Γ, x : τ ′; δ ` x : τ(H2) Γ; δ ` v : τ ′

(3) τ = τ ′ from (H1)(4) x{v/x} = v by Definition 14(5) ? Γ; δ ` v : τ from (H2, 3, 4)

3. Variable x 6= y(H1) Γ, x : τ ′; δ ` y : τ(H2) Γ; δ ` v : τ ′

(3) y{v/x} = y by Definition 14(4) ? Γ; δ ` y : τ from (H1, 3)

4. Name(H1) Γ, x : τ ′; δ ` a : τ with τ = varδ′(τ

′′) ∨ τ = defδ′(τ′′)

(H2) Γ; δ ` v : τ ′

(3) a{v/x} = a by Definition 14(4) ? Γ; δ ` a : τ from (H1, 3)

5. Action(H1) Γ, x : τ ′; δ ` action { a := e } : Action(H2) Γ; δ ` v : τ ′

(action { a := e }){v/x} = action { a := e{v/x} } by Definition 14i = 1, . . . , n

(3) Γ, x : τ ′; δ ` ai := ei by inv. of ACTION in (H1)δ = δ′ ∪ {a}

(4) Γ, x : τ ′; δ′ ` ei : τi by inv. of ASSIGN in (3)(5) Γ; δ′ ` ei{v/x} by I.H. with (4, H2)(6) Γ; δ′ ∪ {a} ` ai := ei{v/x} by ASSIGN in (5)(7) ? Γ; δ ` action { a := e{v/x} } : Action by ACTION with (6)

6. Abstraction(H1) Γ, x : τ ′; δ ` λy.e : τy → τe(H2) Γ; δ ` v : τ ′

x 6= y(λy.e){v/x} = λy.(e{v/x}) by Definition 14

(3) Γ, x : τ ′, y : τy; δ ` e : τe by inv. of ABS in (H1)(4) Γ, y : τy; δ ` e{v/x} : τe by I.H. with (3, H2)(5) ? Γ; δ ` λy.(e{v/x}) : τe by ABS in (4)

7. Application(H1) Γ, x : τ ′; δ ` e e′ : τ(H2) Γ; δ ` v : τ ′

(e e′){v/x} = (e{v/x}) (e′{v/x}) by Definition 14(3) Γ, x : τ ′; δ ` e : τa → τ by inv. of APP in (H1)(4) Γ, x : τ ′; δ ` e′ : τa by inv. of APP in (H1)(5) Γ; δ ` e{v/x} : τa → τ by I.H. with (H2, 3)(6) Γ; δ ` e′{v/x} : τa by I.H. with (H2, 4)(7) ? Γ; δ ` (e{v/x}) (e′{v/x}) : τ by APP with (5, 6)

8. Binary Operation(H1) Γ, x : τ ′′′; δ ` e op e′ : τ ′′

(H2) Γ; δ ` v : τ ′′′

(e op e′){v/x} = (e{v/x}) op (e′{v/x}) by Definition 14

14 2014/6/9

Page 15: Type-Safe Evolution of Data-Centric Applicationsmiguel.domingues.pt/docs/techreport-2014.pdf · Which means that applications may evolve without any service dis-ruption. We use a

op: τ → τ ′ → τ ′′

(3) Γ, x : τ ′′′; δ ` e : τ by inv. of OP on (H1)(4) Γ, x : τ ′′′; δ ` e′ : τ ′ by inv. of OP on (H1)(5) Γ; δ ` e{v/x} : τ by I.H. with (H2, 3)(6) Γ; δ ` e′{v/x} : τ by I.H. with (H2, 4)(7) ? Γ; δ ` e{v/x} op e′{v/x} : τ ′′ by OP with (5, 6)

9. Conditional(H1) Γ, x : τ ′; δ ` (e ? e′ : e′′) : τ(H2) Γ; δ ` v : τ ′

(e ? e′ : e′′){v/x} = (e{v/x}) ? (e′{v/x}) : (e′′{v/x}) by Definition 14(3) Γ, x : τ ′; δ ` e : Bool by inv. of IF on (H1)(4) Γ, x : τ ′; δ ` e′ : τ by inv. of IF on (H1)(5) Γ, x : τ ′; δ ` e′′ : τ by inv. of IF on (H1)(6) Γ; δ ` e{v/x} : Bool by I.H. with (H2, 3)(7) Γ; δ ` e′{v/x} : τ by I.H. with (H2, 4)(8) Γ; δ ` e′′{v/x} : τ by I.H. with (H2, 5)(9) ? Γ; δ ` (e{v/x}) ? (e′{v/x}) : (e′′{v/x}) : τ by IF with (6, 7, 8)

10. Collection(H1) Γ, x : τ ′; δ ` [e1, . . . , en] : τ∗

(H2) Γ; δ ` v : τ ′

[e1, . . . , en]{v/x} = [e1{v/x}, . . . , en{v/x}] by Definition 14(3) Γ, x : τ ′; δ ` ei : τ by inv. of COLLECTION on (H1)

i = 1, . . . , n(4) Γ; δ ` ei{v/x} : τ by I.H. with (H2, 3)(5) ? Γ; δ ` [e1{v/x}, . . . , en{v/x}] : τ∗ by COLLECTION with (4)

11. Iterator(H1) Γ, z : τ ′; δ ` iter(e, e′, x.y.e′′) : τ(H2) Γ; δ ` v : τ ′

iter(e, e′, x.y.e′′){v/z} = iter(e{v/z}, e′{v/z}, x.y.e′′{v/z}) by Definition 14(3) Γ, z : τ ′; δ ` e : τ ′′∗ by inv. of ITER in (H1)(4) Γ, z : τ ′; δ ` e′ : τ by inv. of ITER in (H1)(5) Γ, z : τ ′, x : τ ′′, y : τ ; δ ` e′′ : τ by inv. of ITER in (H1)(6) Γ; δ ` e{v/z} : τ ′′∗ by I.H. with (H2, 3)(7) Γ; δ ` e′{v/z} : τ by I.H. with (H2, 4)(8) Γ, x : τ ′′, y : τ ; δ ` e′′{v/z} : τ by I.H. with (H2, 5)(9) ? Γ; δ ` iter(e{v/z}, e′{v/z}, x.y.e′′{v/z}) : τ by ITER with (6, 7, 8)

12. Match(H1) Γ, x : τ ′; δ `match e with y::ys→ e′ | [ ]→ e′′ : τ(H2) Γ; δ ` v : τ ′

(match e with y::ys→ e′ | [ ]→ e′′){v/x} == match (e{v/x}) with y::ys→ (e′{v/x}) | [ ]→ (e′′{v/x}) by Definition 14

(3) Γ, x : τ ′; δ ` e : τ ′′∗ by inv. of MATCH on (H1)(4) Γ, x : τ ′, y : τ ′′, ys : τ ′′∗; δ ` e′ : τ by inv. of MATCH on (H1)(5) Γ, x : τ ′; δ ` e′′ : τ by inv. of MATCH on (H1)(6) Γ; δ ` e{v/x} : τ ′′∗ by I.H. with (H2, 3)(7) Γ, y : τ ′′, ys : τ ′′∗; δ ` e′{v/x} : τ by I.H. with (H2, 4)(8) Γ; δ ` e′′{v/x} : τ by I.H. with (H2, 5)(9) ? Γ; δ `match (e{v/x}) with y::ys→ (e′{v/x}) | [ ]→ (e′′{v/x}) : τ by MATCH with (6, 7, 8)

Lemma 3 (Expressions Progress). For all expression configurations (S; e) and typing environments Γ, ifΓ ` (S; e) and Γ; δ ` e : τ and for all a ∈ δ we have S(a) = (e′′, v, s), then either e is a value, or there isan expression e′ such that S; e −→ e′.

Proof. By induction on the length of the derivation Γ; δ ` e : τ .1. DNAME

(H1) Γ ` (S; a)(H2) Γ, a : defδ′(τ); δ ∪ {a} ` a : τ(H3) S(a) = (e, v, s)

? S; a −→ v by RNAME with (H3)

15 2014/6/9

Page 16: Type-Safe Evolution of Data-Centric Applicationsmiguel.domingues.pt/docs/techreport-2014.pdf · Which means that applications may evolve without any service dis-ruption. We use a

2. VNAME(H1) Γ, a : varδ′(τ); δ ∪ {a} ` a : τ(H2) Γ ` (S; a)(H3) S(a) = (e, v, s)

? S; a −→ v by RNAME with (H3)

3. ID(H1) Γ; δ ` x : τ(H2) Γ ` (S;x)(H3) ∀a ∈ δ.S(a) = (e, v, s)

? x is a value

4. ABS(H1) Γ; δ ` λx.e : τ → τ ′

(H2) Γ ` (S;λx.e)(H3) ∀a ∈ δ.S(a) = (e, v, s)

? λx.e is a value

5. APP(H1) Γ; δ ` e1 e2 : τ ′

(H2) Γ ` (S; e1 e2)(H3) ∀a ∈ δ.S(a) = (e, v, s)

(4) Γ; δ ` e1 : τ → τ ′ by inv. of APP in (H1)(5) Γ; δ ` e2 : τ by inv. of APP in (H1)(6) · | Γ ` S by Definition 11 with (H2)(7) Γ ` (S; e1) by Definition 11 with (6, 4)

S; e1 −→ e′1 ∨ e1 is a value by I.H. with (7, 4, H3)

(8) CASE: S; e1 −→ e′1? S; e1 e2 −→ e′1 e2 by RCONTEXT with (8)

(10) CASE: e1 is a value(11) Γ ` (S; e2) by Definition 11 with (6, 5)

S; e2 −→ e′2 ∨ e2 is a value by I.H. with (11, 5, H3)

(12) SCASE: S; e2 −→ e′2? S; e1 e2 −→ e1 e

′2 by RCONTEXT with (10, 12)

(14) SCASE: e2 is a valuee1 = λx.e′1 from (4, 8)

? S; (λx.e′1) e2 −→ e′1{e2/x} by RAPP with (8, 14)

6. APP(H1) Γ; δ ` e1 op e2 : τ ′′

(H2) Γ ` (S; e1 op e2)(H3) ∀a ∈ δ.S(a) = (e, v, s)

op: τ → τ ′ → τ ′′

(4) Γ; δ ` e1 : τ by inv. of OP in (H1)(5) Γ; δ ` e2 : τ ′ by inv. of OP in (H1)(6) · | Γ ` S by Definition 11 with (H2)(7) Γ ` (S; e1) by Definition 11 with (6, 4)

S; e1 −→ e′1 ∨ e1 is a value by I.H. with (7, 4, H3)

(8) CASE: S; e1 −→ e′1? S; e1 op e2 −→ e′1 op e2 by RCONTEXT with (8)

(10) CASE: e1 is a value(11) Γ ` (S; e2) by Definition 11 with (6, 5)

S; e2 −→ e′2 ∨ e2 is a value by I.H. with (11, 5, H3)

(12) SCASE: S; e2 −→ e′2? S; e1 op e2 −→ e1 op e

′2 by RCONTEXT with (10, 12)

(14) SCASE: e2 is a value? S; e1 op e2 −→ v′ by ROP with (10, 14)

7. IF(H1) Γ; δ ` (e ? e′ : e′′) : τ ′

(H2) Γ ` (S; e ? e′ : e′′)

16 2014/6/9

Page 17: Type-Safe Evolution of Data-Centric Applicationsmiguel.domingues.pt/docs/techreport-2014.pdf · Which means that applications may evolve without any service dis-ruption. We use a

(H3) ∀a ∈ δ.S(a) = (e, v, s)(4) · | Γ ` S by Definition 11 with (H2)(5) Γ; δ ` e : Bool by inv. IF in (H1)(6) Γ ` (S; e) by Definition 11 with (4, 5)

S; e −→ e1 ∨ e is a value by I.H. with (6, 5, H3)

(7) CASE: S; e −→ e1

? S; (e ? e′ : e′′) −→ (e1 ? e′ : e′′) op e2 by RCONTEXT with (7)

(9) CASE: e is a valuee = true ∨ e = false from (5, 9)

(10) SCASE: e = true? S; (true ? e′ : e′′) −→ e′ by RTRUE with (10)

(12) SCASE: e = false? S; (false ? e′ : e′′) −→ e′′ by RTRUE with (12)

8. ITER(H1) Γ; δ ` iter(e1, e2, x.y.e3) : τ ′

(H2) Γ ` (S; iter(e1, e2, x.y.e3))(H3) ∀a ∈ δ.S(a) = (e, v, s)

(4) Γ; δ ` e1 : τ∗ by inv. of ITER in (H1)(5) Γ; δ ` e2 : τ ′ by inv. of ITER in (H1)(6) Γ, x : τ, y : τ ′; δ ` e3 : τ ′ by inv. of ITER in (H1)(7) · | Γ ` S by Definition 11 with (H2)(8) Γ ` (S; e1) by Definition 11 with (7, 4)

S; e1 −→ e′1 ∨ e1 is a value by I.H. with (4, 8, H3)

(9) CASE: S; e1 −→ e′1? S; iter(e1, e2, x.y.e3) −→ iter(e′1, e2, x.y.e3) by RCONTEXT with (9)

(11) CASE: e1 is a value(12) Γ ` (S; e2) by Definition 11 with (7, 5)

S; e2 −→ e′2 ∨ e2 is a value by I.H. with (12, 5, H3)

(13) SCASE: S; e2 −→ e′2? S; iter(e1, e2, x.y.e3) −→ iter(e1, e

′2, x.y.e3) by RCONTEXT with (11, 13)

(15) SCASE: e2 is a valuee1 = [ ] ∨ e1 = [v1, . . . , vn] from (4, 11)

(16) SSCASE: e1 = [ ]? S; iter(e1, e2, x.y.e3) −→ e2 by RNIL with (16, 15)

(18) SSCASE: e1 = [v1, . . . , vn]? S; iter(e1, e2, x.y.e3) −→ iter([v2, . . . , vn], e3{v1/x}{e2/y}, x.y.e3)

by RITERATE with (18, 15)

9. MATCH(H1) Γ; δ `match e1 with x::xs→ e2 | [ ]→ e3 : τ ′

(H2) Γ ` (S;match e1 with x::xs→ e2 | [ ]→ e3)(H3) ∀a ∈ δ.S(a) = (e, v, s)

(4) Γ; δ ` e1 : τ∗ by inv. of MATCH in (H1)(5) Γ, x : τ, xs : τ∗; δ ` e2 : τ ′ by inv. of MATCH in (H1)(6) Γ; δ ` e3 : τ ′ by inv. of MATCH in (H1)(7) · | Γ ` S by Definition 11 with (H2)(8) Γ ` (S; e1) by Definition 11 with (7, 4)

S; e1 −→ e′1 ∨ e1 is a value by I.H. with (8, 4, H3)

(9) CASE: S; e1 −→ e′1? S;match e1 with x::xs→ e2 | [ ]→ e3 −→match e′1 with x::xs→ e2 | [ ]→ e3

by RCONTEXT with (9)

(11) CASE: e1 is a valuee1 = [ ] ∨ e1 = [v1, . . . , vn] from (11, 4)

(12) SCASE: e1 = [ ]? S;match e1 with x::xs→ e2 | [ ]→ e3 −→ e3 by REMPTY with (12)

(14) SCASE: e1 = [v1, . . . , vn]

17 2014/6/9

Page 18: Type-Safe Evolution of Data-Centric Applicationsmiguel.domingues.pt/docs/techreport-2014.pdf · Which means that applications may evolve without any service dis-ruption. We use a

? S;match e1 with x::xs→ e2 | [ ]→ e3 −→ e2{v1/x}{[v2, . . . , vn]/xs}by RMATCH with (14)

10. COLLECTION(H1) Γ; δ ` [e1, . . . , en] : τ∗

(H2) Γ ` (S; [e1, . . . , en])(H3) ∀a ∈ δ.S(a) = (e, v, s)

(4) Γ; δ ` ei : τ by inv. of COLLECTION in (H1)(5) · | Γ ` S by Definition 11 with (H2)(6) Γ ` (S; ei) by Definition 11 with (5, 4)

S; ei −→ e′i ∨ ei is a value by I.H. with (6, 4, H3)

(7) CASE: S; ei −→ e′ie0, . . . , ei−1 are values

? S; [e1, . . . , ei, . . . , en] −→ [e1, . . . , e′i, . . . , en] by RCONTEXT with (7)

(9) CASE: ei is a valuee0, . . . , en are values

? [e1, . . . , en] is a value

11. VALUE(H1) Γ; δ ` b : β(H2) Γ ` (S;b)(H3) ∀a ∈ δ.S(a) = (e, v, s)

? b is a value

12. ACTION(H1) Γ; δ ` action { a := e } : Action(H2) Γ ` (S;action { a := e })(H3) ∀a ∈ δ.S(a) = (e, v, s)

? action { a := e } is a value

Lemma 4 (Expressions Context Type Preservation). For all expression configurations (S; E [e]) and typingenvironments Γ, if Γ; δ ` e : τ ′, and Γ; δ ` e′ : τ ′, then Γ; δ ` E [e′] : τ .

Proof. Straightforward by induction on the structure of E [e].

Lemma 5 (Expressions Type Preservation). For all expression configurations (S; e) and typing environmentsΓ, if Γ ` (S; e) and Γ; δ ` e : τ and an expression reduction S; e −→ e′, then Γ; δ ` e′ : τ .

Proof. By induction on the length of the expression reduction S; e −→ e′.1. RCONTEXT

(H1) Γ ` (S; E [e])(H2) Γ; δ ` E [e] : τ(H3) S; E [e] −→ E [e′]

(4) S; e −→ e′ by inv. of RCONTEXT in (H3)(5) Γ ` S by Definition 11 in (H1)

(6) CASE: E [e] = e op e′′

op: τ → τ ′ → τ ′′

(7) Γ; δ ` e op e′′ : τ ′′ from (H2, 6)(8) Γ; δ ` e : τ by inv. of OP in (7)(9) Γ ` (S; e) by Definition 11 with (5, 8)

(10) Γ; δ ` e′ : τ by I.H. with (9, 8, 4)? Γ; δ ` E [e′] : τ ′′ by Lemma 4 with (H2, 8, 10)

(12) CASE: E [e] = v op eop: τ → τ ′ → τ ′′

(13) Γ; δ ` v op e : τ ′′ from (H2, 12)(14) Γ; δ ` e : τ ′ by inv. of OP in (13)(15) Γ ` (S; e) by Definition 11 with (5, 14)(16) Γ; δ ` e′ : τ ′ by I.H. with (15, 14, 4)

? Γ; δ ` E [e′] : τ ′′ by Lemma 4 with (H2, 14, 16)

(18) CASE: E [e] = e e′′

(19) Γ; δ ` e e′′ : τ from (H2, 18)

18 2014/6/9

Page 19: Type-Safe Evolution of Data-Centric Applicationsmiguel.domingues.pt/docs/techreport-2014.pdf · Which means that applications may evolve without any service dis-ruption. We use a

(20) Γ; δ ` e : τ ′ → τ by inv. of APP in (19)(21) Γ ` (S, e) by Definition 11 with (5, 20)(22) Γ; δ ` e′ : τ ′ → τ by I.H. with (21, 20, 4)

? Γ; δ ` E [e′] : τ by Lemma 4 with (H2, 20, 22)

(24) CASE: E [e] = (λx.e′′) e(25) Γ; δ ` (λx.e′′) e : τ from (H2, 24)(26) Γ; δ ` e : τ ′ by inv. of APP in (25)(27) Γ ` (S; e) by Definition 11 with (5, 26)(28) Γ; δ ` e′ : τ ′ by I.H. with (28, 26, 4)

? Γ; δ ` E [e′] : τ by Lemma 4 with (H2, 26, 28)

(30) CASE: E [e] = [v1, . . . , vi, e, ei+2, . . . , en](31) Γ; δ ` [v1, . . . , vi, e, ei+2, . . . , en] : τ ′∗ from (H2, 30)(32) Γ; δ ` e : τ ′ by inv. of COLLECTION in (31)(33) Γ ` (S; e) by Definition 11 with (5, 32)(34) Γ; δ ` e′ : τ ′ by I.H. with (33, 32, 4)

? Γ; δ ` E [e′] : τ ′∗ by Lemma 4 with (H2, 32, 34)

(36) CASE: E [e] = iter(e, e′′, x.y.e′′′)(37) Γ; δ ` iter(e, e′′, x.y.e′′′) : τ from (H2, 36)(38) Γ; δ ` e : τ ′∗ by inv. of ITER in (37)(39) Γ ` (S; e) by Definition 11 with (5, 38)(40) Γ; δ ` e′ : τ ′∗ by I.H. with (39, 38, 4)

? Γ; δ ` E [e′] : τ by Lemma 4 with (H2, 38, 40)

(42) CASE: E [e] = iter(v, e, x.y.e′′)(43) Γ; δ ` iter(v, e, x.y.e′′) : τ from (H2, 42)(44) Γ; δ ` e : τ by inv. of ITER in (43)(45) Γ ` (S; e) by Definition 11 with (5, 44)(46) Γ; δ ` e′ : τ by I.H. with (45, 44, 4)

? Γ; δ ` E [e′] : τ by Lemma 4 with (H2, 44, 46)

(48) CASE: E [e] = match e with x::xs→ e′′ | [ ]→ e′′′

(49) Γ; δ `match e with x::xs→ e′′ | [ ]→ e′′′ : τ from (H2, 48)(50) Γ; δ ` e : τ ′∗ by inv. of MATCH in (49)(51) Γ ` (S; e) by Definition 11 with (5, 50)(52) Γ; δ ` e′ : τ ′∗ by I.H. with (51, 50, 4)

? Γ; δ ` E [e′] : τ by Lemma 4 with (H2, 50, 52)

2. RNAME(H1) Γ ` (S; a)(H2) Γ; δ ` a : τ(H3) S; a −→ v

(4) S(a) = (e, v, s) by inv. of RNAME in (H2)(5) · | Γ ` S by Definition 11 with (H1)

? Γ; δ ` v : τ by Definition 9 with (5, 4, H2)

3. RAPP(H1) Γ ` (S; (λx.e) v)(H2) Γ; δ ` (λx.e) v : τ ′

(H3) S; (λx.e) v −→ e{v/x}(4) Γ; δ ` λx.e : τ → τ ′ by inv. of APP in (H2)(5) Γ; δ ` v : τ by inv. of APP in (H2)(6) Γ, x : τ ; δ ` e : τ ′ by inv. of ABS in (4)

? Γ; δ ` e{v/x} : τ ′ by Lemma 2 with (6, 5)

4. ROP(H1) Γ ` (S; v op v′)(H2) Γ; δ ` v op v′ : τ ′′

(H3) S; v op v′ −→ v′′

(4) op: τ → τ ′ → τ ′′

Γ; δ ` v : τ by inv. of OP in (H2)Γ; δ ` v′ : τ ′ by inv. of OP in (H2)

(5) v′′ = [[v op v′]] by inv. of ROP in (H3)? Γ; δ ` v′′ : τ ′′ from (4, 5)

19 2014/6/9

Page 20: Type-Safe Evolution of Data-Centric Applicationsmiguel.domingues.pt/docs/techreport-2014.pdf · Which means that applications may evolve without any service dis-ruption. We use a

5. RTRUE(H1) Γ ` (S; true ? e : e′)(H2) Γ; δ ` true ? e : e′ : τ(H3) S; true ? e : e′ −→ e

? Γ; δ ` e : τ by inv. of RTRUE in (H2)

6. RFALSE(H1) Γ ` (S; false ? e : e′)(H2) Γ; δ ` false ? e : e′ : τ(H3) S; false ? e : e′ −→ e

? Γ; δ ` e : τ by inv. of RFALSE in (H2)

7. RNIL(H1) Γ ` (S; iter([ ], v, x.y.e))(H2) Γ; δ ` iter([ ], v, x.y.e) : τ(H3) S; iter([ ], v, x.y.e) −→ v

? Γ; δ ` v : τ by inv. of ITER in (H2)

8. RITERATE(H1) Γ ` (S; iter(z::zs, v, x.y.e))(H2) S; iter(z::zs, v, x.y.e) −→ iter(zs, e{z/x}{v/y}, x.y.e)(H3) Γ; δ ` iter(z::zs, v, x.y.e) : τ ′

(4) Γ; δ ` z::zs : τ∗ by inv. of ITER in (H3)(5) Γ; δ ` v : τ ′ by inv. of ITER in (H3)(6) Γ, x : τ, y : τ ′; δ ` e : τ ′ by inv. of ITER in (H3)(7) Γ; δ ` z : τ by inv. of OP in (4)(8) Γ; δ ` zs : τ∗ by inv. of OP in (4)(9) Γ, y : τ ′; δ ` e{z/x} : τ ′ by Lemma 2 with (6, 7)

(10) Γ; δ ` e{z/x}{v/y} : τ ′ by Lemma 2 with (9, 5)? Γ; δ ` iter(zs, e{z/x}{v/y}, x.y.e) : τ ′ by ITER with (8, 10, 6)

9. REMPTY(H1) Γ ` (S;match [ ] with x::xs→ e | [ ]→ e′)(H2) Γ; δ ` (match [ ] with x::xs→ e | [ ]→ e′) : τ(H3) S; (match [ ] with x::xs→ e | [ ]→ e′) −→ e′

? Γ; δ ` e′ : τ by inv. of MATCH in (H2)

10. RMATCH(H1) Γ ` (S;match v::vs with x::xs→ e | [ ]→ e′)(H2) Γ; δ ` (match v::vs with x::xs→ e | [ ]→ e′) : τ ′

(H3) S; (match v::vs with x::xs→ e | [ ]→ e′) −→ e{v/x}{vs/xs}(4) Γ; δ ` v::vs : τ∗ by inv. of MATCH in (H2)(5) Γ, x : τ, xs : τ∗; δ ` e : τ by inv. of MATCH in (H2)(6) Γ; δ ` v : τ by OP and (4)(7) Γ; δ ` vs : τ∗ by OP and (4)(8) Γ, xs : τ∗; δ ` e{v/x} by Lemma 2 with (5, 6)

? Γ; δ ` e{v/x}{vs/xs} by Lemma 2 with (8, 7)

Corollary 1 (Equal Domains). For all typing environments Γ and Γ′, and states S, if Γ | Γ′ ` S, thendom(Γ′) = dom(S).Lemma 6 (Weakening on Well-typed States). For all typing environments Γ and states S such that a 6∈dom(Γ) and · | Γ ` S and Γ; δ ` e : τ ,1. If a : defδ(τ) then, · | Γ, a : defδ(τ) ` S, a 7→ (e,�, [ ]).2. If a : varδ(τ) then, · | Γ, a : varδ(τ) ` S, a 7→ (e,�, [ ]).

Proof. We prove for each case based on the well-typed states, and well-formed queue definitions.1. Definition Name

(H1) · | Γ ` S(H2) Γ; δ ` e : τ(H3) a 7→ (e,�, [ ])(H4) a 6∈ dom(Γ)

(5) Γ | · ` · by Definition 9 in (H1)(6) Γ, a : defδ(τ) | · ` · by Definition 9 with (H4)(7) S, a 7→ (e,�, [ ]); Γ ` [ ] by Definition 7

20 2014/6/9

Page 21: Type-Safe Evolution of Data-Centric Applicationsmiguel.domingues.pt/docs/techreport-2014.pdf · Which means that applications may evolve without any service dis-ruption. We use a

(8) S, a 7→ (e,�, [ ]); Γ ` [a] by Definition 7 with (7)(9) δ ⊆ dom(Γ) from (H2)

(10) uΓ(δ) ⊆ dom(Γ) from (9)(11) [ ] ⊆ ∅(12) Γ | a : defδ(τ) ` a 7→ (e,�, [ ]) by Definition 9 with (H2, 6, 8, 10, 11)

? · | Γ, a : defδ(τ) ` S, a 7→ (e,�, [ ]) by Definition 9 with (5, 12)

2. Variable Name(H1) · | Γ ` S(H2) Γ; δ ` e : τ(H3) a 7→ (e,�, [ ])(H4) a 6∈ dom(Γ)

(5) Γ | · ` · by Definition 9 in (H1)(6) Γ, a : varτ ( | )· ` · by Definition 9(7) S, a 7→ (e,�, [ ]); Γ ` [ ] by Definition 7(8) S, a 7→ (e,�, [ ]); Γ ` [a] by Definition 7 with (7)(9) [ ] ⊆ ∅

(10) tS(δ) = [ ] from (9)(11) tS(δ) ⊆ dom( · ) from (10)(12) Γ | a : varδ(τ) ` a 7→ (e,�, [ ]) by Definition 9 with (H2, 6, 8, 11)

? · | Γ, a : varδ(τ) ` S, a 7→ (e,�, [ ]) by Definition 9 with (5, 12)

Lemma 7. For all typing environments Γ and states S such that · | Γ ` S then, for all b ∈ tS({a})⇒ a ∈uΓ({b}).

Proof. We prove by contradiction.1.

(H1) tS({a}) ∩ uΓ({a}) = ∅(2) ∃b. b ∈ tS({a}) ∧ b ∈ uΓ({a})(3) a ∈ uΓ({b}) from (2)(4) uΓ({b}) ⊆ uΓ({a}) from (2)(5) a ∈ uΓ({a}) from (3, 4)

a 6∈ uΓ({a}) Contradiction (H1, 5)

Lemma 8 (Inversion). For all typing environments Γ,Γ′ and states S such that Γ | Γ′, a : defδ(τ) `S, a 7→ (e, v, s) then, there is a typing environment Γ1,Γ

′1 and a state S1,S ′1 such that Γ,Γ′ = Γ1,Γ

′1, and

S = S1,S ′1, and tS′

1(s) = dom(S ′1) = dom(Γ′1) and Γ1 | Γ′1, a : defδ(τ) ` S ′1, a 7→ (e, v, s).

Proof. Follows directly from the definition of well-typed states (Definition 9) and Lemma 7.

Theorem 1 (Progress of Programs). For all program configurations (S;P;L) if Γ ` (S;P;L) and∀a ∈ dom(S). (S(a) = (e,�, s) ⇒ L = [a]), then there is a program configuration (S ′;P ′;L′) suchthat (S;P;L) −→ (S ′;P ′;L′) and ∀a ∈ dom(S ′). (S ′(a) = (e,�, s)⇒ L′ = [a]).

Proof. By induction on the length of the derivation Γ ` P we prove for the cases where L = [ ] and L 6= [ ].1. a::L 6= [ ]

(H1) Γ ` (S;P; a::L)(H2) ∀a ∈ dom(S). (S(a) = (e,�, s)⇒ a::L = [a])

(3) · | Γ ` S by Definition 10 in (H1)S(a) = (e, v′, s)

(4) S = S[a 7→ (e, v′, s)]? (S[a 7→ (e, v, s)];P; a::L) −→ (S[a 7→ (e, v, s)];P; a〈e〉::L) by RQEXP with (4)? ∀a ∈ dom(S). (S(a) = (e,�, s)⇒ a::L = [a]) from (H2, 4)

2. a〈e〉::L 6= [ ](H1) Γ ` (S;P; a〈e〉::L)(H2) ∀a ∈ dom(S). (S(a) = (e,�, s)⇒ a ::L = [a])

(3) · | Γ ` S by Definition 10 in (H1)(4) S; Γ ` a〈e〉::L by Definition 10 in (H1)(5) Γ; δ ` e : τ by Definition 7 in (4)(6) Γ ` (S; e) by Definition 11 with (3, 5)(7) a 6∈ δ by Definition 9 in (3)

21 2014/6/9

Page 22: Type-Safe Evolution of Data-Centric Applicationsmiguel.domingues.pt/docs/techreport-2014.pdf · Which means that applications may evolve without any service dis-ruption. We use a

S(a) = (e, v′, s)e is a value ∨ (S; e) −→ e′ by Lemma 3 with (6, 5, 7)

CASE: e is a valuee = v

? (S;P; a〈e〉::L) −→ (S[a 7→ (e, v, s)];P;L@s) by RQVAL

(10) CASE: (S; e) −→ e′

? (S;P; a〈e〉::L) −→ (S;P; a〈e′〉::L) by RQSTEP with (10)? ∀a ∈ dom(S). (S(a) = (e,�, s)⇒ a::L = [a])

3. L = [ ](H1) Γ ` (S;P; [ ])(H2) ∀a ∈ dom(S). (S(a) = (e,�, s)⇒ L = [a])

(3) Γ ` S by Definition 10 in (H1)(4) dom(Γ) = dom(S) by Corollary 1 with (H1)

CASE: DEFP = def a = e,P ′

(6) Γ ` def a = e,P ′ by Definition 10 in (H1)(7) a 6∈ dom(Γ) by inv. of DEF in (6)(8) a 6∈ dom(S) by (7, 4)(9) ψ(S, a) = [ ] by def. of ψ with (8)

(10) S ′ = subscribe(S, a, e)? (S;def a = e,P ′; [ ]) −→ (S ′[a 7→ (e,�, [ ])];P ′; [a]) by RDEF with (10, 9)

(12) ∀a ∈ dom(S ′). (S ′(a) = (e, v, s)) from (H2, 10)S ′′ = S ′[a 7→ (e,�, [ ])]

? ∀a ∈ dom(S ′′). (S ′′(a) = (e,�, s)⇒ [a] = [a]) from (12)

CASE: VARP = var a = e,P ′

(15) Γ ` var a = e,P ′ by Definition 10 in (H1)(16) a 6∈ dom(Γ) by inv. of VAR in (15)(17) a 6∈ dom(S) by (16, 4)(18) ψ(S, a) = [ ] by def. of ψ and (17)

? (S;var a = e,P ′; [ ]) −→ (S[a 7→ (e,�, [ ])];P ′; [a]) by RVAR with (18)(20) ∀a ∈ dom(S). (S(a) = (e, v, s)) from (H2)

? ∀a ∈ dom(S[a 7→ (e,�, [ ])]). (S(a) = (e,�, s)⇒ [a] = [a]) from (20)

CASE: DOP = do e,P ′

(23) Γ ` do e,P ′ by Definition 10 in (H1)(24) Γ; δ ` e : Action by inv. of DO in (23)(25) S; e −→ e′ by Lemma 3 with (H2, 24)

? (S;do e,P ′; [ ]) −→ (S;do e′,P ′; [ ]) by RDO with (25)? ∀a ∈ dom(S). (S(a) = (e,�, s)⇒ L = [a]) from (H2)

CASE: UVARP = var a = e,P ′Γ = Γ′, a : varδ(τ)Γ′, a : varδ(τ) ` var a = e,P ′ by Definition 10 in (H1)

(29) a ∈ dom(Γ′, a : varδ(τ))(30) a ∈ dom(S) by (29, 4)(31) ψ(S, a) = s by def. of ψ and (30)

? (S;var a = e,P ′; [ ]) −→ (S[a 7→ (e,�, s)];P ′; [a]) by RVAR with (31)(33) S ′ = S[a 7→ (e,�, s)]

? ∀a ∈ dom(S ′). (S ′(a) = (e,�, s)⇒ [a] = [a]) from (H2, 33)

CASE: UVARTP = var a = e,P ′Γ = Γ′, a : varδ(τ)Γ′, a : varδ(τ) ` var a = e,P ′ by Definition 10 in (H1)

(36) a ∈ dom(Γ′, a : varδ(τ))(37) a ∈ dom(S) by (36, 4)(38) ψ(S, a) = s by def. of ψ and (37)

? (S;var a = e,P ′; [ ]) −→ (S[a 7→ (e,�, s)];P ′; [a]) by RVAR with (38)(40) S ′ = S[a 7→ (e,�, s)]

? ∀a ∈ dom(S ′). (S ′(a) = (e,�, s)⇒ [a] = [a]) from (H2, 40)

22 2014/6/9

Page 23: Type-Safe Evolution of Data-Centric Applicationsmiguel.domingues.pt/docs/techreport-2014.pdf · Which means that applications may evolve without any service dis-ruption. We use a

CASE: UDEFP = def a = e,P ′Γ = Γ′, a : defδ(τ)Γ′, a : defδ(τ) ` def a = e,P ′ by Definition 10 in (H1)

(43) a ∈ dom(Γ′, a : defδ(τ))(44) a ∈ dom(S) by (43, 4)(45) ψ(S, a) = s by def. of ψ and (44)(46) S ′ = subscribe(S, a, e)

? (S;def a = e,P ′; [ ]) −→ (S ′[a 7→ (e,�, s)];P ′; [a]) by RDEF with (45, 46)(48) ∀a ∈ dom(S ′). (S ′(a) = (e, v, s)) from (H2, 46)

S ′′ = S ′[a 7→ (e,�, s)]? ∀a ∈ dom(S ′′). (S ′′(a) = (e,�, s)⇒ [a] = [a]) from (48)

CASE: UDEFTP = def a = e,P ′Γ = Γ′, a : defδ(τ)Γ′, a : defδ(τ) ` def a = e,P ′

(51) a ∈ dom(Γ′, a : defδ(τ))(52) a ∈ dom(S) by (51, 4)(53) ψ(S, a) = s by def. of ψ and (52)(54) S ′ = subscribe(S, a, e)

? (S;def a = e,P ′; [ ]) −→ (S ′[a 7→ (e,�, s)];P ′; [a]) by RDEF with (53, 54)(56) ∀a ∈ dom(S ′). (S ′(a) = (e, v, s)) from (H2, 46)

S ′′ = S ′[a 7→ (e,�, s)]? ∀a ∈ dom(S ′′). (S ′′(a) = (e,�, s)⇒ [a] = [a]) from (56)

CASE: VARDEFP = def a = e,P ′Γ = Γ′, a : varδ(τ)Γ, a : varδ(τ) ` def a = e,P

(59) a ∈ dom(Γ, a : varδ(τ))(60) a ∈ dom(S) by (59, 4)(61) ψ(S, a) = s by def. of ψ and (60)(62) S ′ = subscribe(S, a, e)

? (S;def a = e,P; [ ]) −→ (S ′[a 7→ (e,�, s)];P; [a]) by RDEF with (61, 62)S ′′ = S ′[a 7→ (e,�, s)]

? ∀a ∈ dom(S ′′). (S ′′(a) = (e,�, s)⇒ [a] = [a]) from (56)

Lemma 9. For all states S and typing environments Γ and Γ′, if Γ | Γ′ ` S then ∀a ∈ dom(S). mS (a) ↑.

Proof. By induction on the well-typed state derivation.1. Γ | · ` ·

Trivially true for empty state

2. Γ | a : varδ(τ),Γ′ ` S, a 7→ (e, o, s)(1) Γ, a : varδ(τ) | Γ′ ` S by Definition 9(2) tS(s) ⊆ dom(Γ′) by Definition 9(3) ∀b ∈ dom(S). mS (b) ↑ by I.H. in (1)(4) dom(Γ′) = dom(S) from Corollary 1 with (1)(5) s ⊆ dom(S) from (2, 4)(6) mS (a) = 1 +

∑b∈smS (b) by Definition 12

? mS (a) ↑ from (6, 5, 3)

3. Γ | a : defδ(τ),Γ′ ` S, a 7→ (e, o, s)(1) Γ, a : defδ(τ) | Γ′ ` S by Definition 9(2) tS(s) ⊆ dom(Γ′) by Definition 9(3) ∀b ∈ dom(S). mS (b) ↑ by I.H. in (1)(4) dom(Γ′) = dom(S) from Corollary 1 with (1)(5) s ⊆ dom(S) from (2, 4)(6) mS (a) = 1 +

∑b∈smS (b) by Definition 12

? mS (a) ↑ from (6, 5, 3)

Lemma 10 (Length Defined). For all configurations (S;P;L), and typing environments Γ, if Γ ` (S,P,L)then mS (L) ↑.

23 2014/6/9

Page 24: Type-Safe Evolution of Data-Centric Applicationsmiguel.domingues.pt/docs/techreport-2014.pdf · Which means that applications may evolve without any service dis-ruption. We use a

Proof. Follows directly from Lemma 9 and the condition L ⊆ dom(S).

Theorem 2 (Programs Type Preservation). For all configurations (S;P;L) and (S ′;P ′;L′), and typingenvironments Γ, if Γ ` (S;P;L) and (S;P;L) −→ (S ′;P ′;L′) then, there is a typing environment Γ′,such that Γ′ ` (S ′,P ′,L′).

Proof. By induction on the length of the program reduction (S;P;L) −→ (S ′;P ′;L′).1. RDEF

(H1) Γ ` (S;def a = e,P; [ ])(H2) (S;def a = e,P; [ ]) −→ (S ′[a 7→ (e,�, s)];P; [a])

(3) Γ ` def a = e,P by Definition 10 in (H1)(4) dom(Γ) = dom(S) by Corollary 1 with (H1)(5) S; Γ ` [ ] by Definition 10 in (H1)(6) · | Γ ` S by Definition 10 in (H1)

a 6∈ dom(Γ) ∨ a ∈ dom(Γ)

(7) CASE: a 6∈ dom(Γ)(8) a 6∈ dom(S) from (8, 7)(9) Γ; δ ` e : τ by inv. of DEF in (3)

(10) Γ, a : defδ(τ) ` P by inv. of DEF in (3)(11) uΓ(δ) ⊆ dom(Γ) from (9)(12) · | Γ, a : defδ(τ) ` S, a 7→ (e,�, [ ]) by Lemma 6 with (7, 6, 9)(13) S ′ = subscribe(S, a, e) by inv. of RDEF in (H2)(14) S ′, a 7→ (e,�, [ ]) = S ′[a 7→ (e,�, [ ])] from (13, 8)(15) · | Γ, a : defδ(τ) ` S ′[a 7→ (e,�, [ ])] from (12, 13, 14)(16) S ′[a 7→ (e,�, [ ])]; Γ ` [ ] by Definition 7(17) ψ(S ′[a 7→ (e,�, [ ])], a) = [ ] by Definition 1(18) S ′[a 7→ (e,�, [ ])]; Γ ` [a] by Definition 7 with (16, 17)

? Γ, a : defδ(τ) ` (S ′[a 7→ (e,�, [ ])];P; [a]) by Definition 10 with (15, 10, 18)

(20) CASE: a ∈ dom(Γ)

(21) SCASE: e and e′have same type (UDEF)Γ = Γ′, a : defδ(τ)Γ′; δ ` e : τ by inv. of UDEF in (3)

(22) a 6∈ uΓ′(δ) by inv. of UDEF in (3)

(23) Γ′, a : defδ(τ) ` P by inv. of UDEF in (3)(24) Γ1 | Γ′1, a : defδ′(τ) ` S ′1, a 7→ (e′, v′, s′) by Lemma 8 with (6)(25) Γ′ = Γ1,Γ

′1 by Lemma 8 with (6)

(26) S = S1, a 7→ (e′, v′, s′),S ′1 by Lemma 8 with (6)(27) t

S′1(s) = dom(S ′1) = dom(Γ1) by Lemma 8 with (6)

(28) S ′1, a 7→ (e′, v′, s); Γ′1 ` [a] (∀e′, v′) by inv. of Definition 9 in (24)uΓ1

(δ) ⊆ dom(Γ1) by inv. of Definition 9 in (24)(29) a 6∈ dom(Γ1) from (22, 25)

a 6∈ tS′

1(s) from (27, 29)

dom(Γ′1) ∩ dom(Γ1) = ∅ from (25)(30) δ ∩ tS(s′) = ∅ by Lemma 7(31) Γ1 | Γ′1, a : defδ(τ) ` S ′1, a 7→ (e,�, s′) from (24, 30)(32) S ′ = subscribe(S, a, e) by inv. of RDEF in (H2)(33) S ′[a 7→ (e′,�, s)] = S1, a 7→ (e′,�, s′),S ′1 from (26, 32)(34) · | Γ′, a : defδ(τ) ` S ′[a 7→ (e′,�, s)] by Definition 9 in (31) with (25, 33)(35) S ′[a 7→ (e′,�, s)] ` [a] from (28, 33)

? Γ′ ` (S ′[a 7→ (e′,�, s)];P; [a]) by Definition 10 with (34, 23, 35)

(37) SCASE: e and e′have different types (UDEFT)Γ = Γ′, a : defδ′(τ

′)S ′ = subscribe(S, e, a) by inv. of RDEF in (H2)s = ψ(S, a) by inv. of RDEF in (H2)

(38) · | Γ′, a : defδ′(τ′) ` S ′

(39) Γ′; δ ` e : τ by inv. of UDEFT in (3)a 6∈ u

Γ′(δ) by inv. of UDEFT in (3)(40) a 6∈ ρ(Γ′) by inv. of UDEFT in (3)(41) Γ′, a : defδ(τ) ` P by inv. of UDEFT in (3)(42) s = [ ] from (40)

S ′ = S ′′, a 7→ (e′, o, s)Γ′ | a : defδ′(τ

′) ` a 7→ (e′, o, s) by Definition 9 in (38) with (40)

24 2014/6/9

Page 25: Type-Safe Evolution of Data-Centric Applicationsmiguel.domingues.pt/docs/techreport-2014.pdf · Which means that applications may evolve without any service dis-ruption. We use a

(43) · | Γ′ ` S ′′ Isolation in (38) with (42)(44) · | Γ′, a : defδ(τ) ` S ′′, a 7→ (e,�, [ ]) by Lemma 6 with (43, 39)

S ′[a 7→ (e,�, s)] = S ′′, a 7→ (e,�, [ ])(45) S ′[a 7→ (e,�, s)]; Γ′ ` [a] by Definition 7 with (42)

? Γ′, a : defδ(τ) ` (S ′[a 7→ (e,�, s)];P; [a]) by Definition 10 with (44, 41, 45)

(47) SCASE: VARDEFSimilar to the above sub-cases.

2. RVARSimilar to RDEF cases.

3. RASSIGN(H1) Γ ` (S[a 7→ (e′′, o, s)];doaction { a := e; a′ := e′ },P; [ ])(H2) (S[a 7→ (e′′, o, s)];doaction { a := e; a′ := e′ },P; [ ])

−→ (S[a 7→ (e′′, o, s)];doaction { a′ := e′ },P; [ ])(3) · | Γ ` S by Definition 10 in (H1)(4) Γ ` doaction { a := e; a′ := e′ },P by Definition 10 in (H1)(5) S; Γ ` [ ] by Definition 10 in (H1)(6) Γ; δ ` action { a := e; a′ := e′ } : Action by inv. of DO in (4)(7) Γ ` P by inv. of DO in (4)

Γ; δ ` a := e by inv. of ACTION in (6)(8) Γ; δ ` a′i := e′i by inv. of ACTION in (6)(9) Γ; δ ` action { a′ := e′ } : Action by DO with (8)

(10) Γ ` doaction { a′ := e′ },P by DO with (9, 7)? Γ ` (S;do e′,P; [ ]) by Definition 10 with (3, 10, 5)

4. RQEXP(H1) Γ ` (S[a 7→ (e, o, s)];P; a::L)(H2) (S[a 7→ (e, o, s)];P; a::L) −→ (S[a 7→ (e, o, s)];P; a〈e〉::L)

(3) · | Γ ` S[a 7→ (e, o, s)] by Definition 10 in (H1)(4) Γ ` P by Definition 10 in (H1)(5) S[a 7→ (e, o, s)]; Γ ` a::L by Definition 10 in (H1)(6) Γ; δ ` e : τ by Definition 9 with (3)(7) S[a 7→ (e, o, s)]; Γ ` a〈e〉::L by Definition 7 with (5, 6)(8) Γ ` (S[a 7→ (e, o, s)];P; a〈e〉::L) by inv. of Definition 10 with (3, 4, 7)

5. RQSTEP(H1) Γ ` (S;P; a〈e〉::L)(H2) (S;P; a〈e〉::L) −→ (S;P; a〈e′〉::L)

(3) · | Γ ` S by Definition 10 in (H1)(4) Γ ` P by Definition 10 in (H1)(5) S; Γ ` a〈e〉::L by Definition 10 in (H1)

Γ = Γ′, a : varδ(τ) ∨ Γ = Γ′, a : defδ(τ)(6) Γ′; δ ` e : τ by Definition 7 in (5)(7) S; Γ ` a::L by Definition 7 in (5)(8) S; e −→ e′ by RQSTEP in (H2)(9) Γ′; δ ` e′ : τ by Lemma 5 with (6, 8)

(10) S; Γ ` a〈e′〉::L by Definition 7 with (9, 7)Γ ` (S;P; a〈e′〉::L) by Definition 10 with (3, 4, 10)

6. RQVAL(H1) Γ ` (S[a 7→ (e, o, s)];P; a〈v〉::L)(H2) (S[a 7→ (e, o, s)];P; a〈v〉::L) −→ (S[a 7→ (e, v, s)];P;L@s)

(3) · | Γ ` S by Definition 10 in (H1)(4) Γ ` P by Definition 10 in (H1)(5) S; Γ ` a〈v〉::L by Definition 10 in (H1)(6) Γ; δ ` v : τ by Definition 7 in (5)

S; Γ ` L@s by Definition 7 in (5)a : defδ(τ) ∨ a : varδ(τ)

(7) CASE: a : defδ(τ)Γ = Γ1, a : defδ(τ),Γ2

(8) S = S2, a 7→ (e, o, s),S1

(9) Γ1 | a : defδ(τ),Γ2 ` S2, a 7→ (e, o, s) by Definition 9 in (3)

25 2014/6/9

Page 26: Type-Safe Evolution of Data-Centric Applicationsmiguel.domingues.pt/docs/techreport-2014.pdf · Which means that applications may evolve without any service dis-ruption. We use a

(10) Γ1; δ ` e : τ by Definition 9 in (9)(11) Γ1, a : defδ(τ) | Γ2 ` S2 by Definition 9 in (9)(12) S2, a 7→ (e, o, s); Γ2 ` [a] by Definition 9 in (9)(13) uΓ1

(δ) ⊆ dom(Γ1) by Definition 9 in (9)(14) tS2

(s) ⊆ dom(Γ2) by Definition 9 in (9)(15) S2, a 7→ (e, v, s); Γ2 ` [a] by Definition 7 and (12)(16) Γ1; δ ` v : τ from (6, 13)(17) Γ1 | a : defδ(τ),Γ2 ` S2, a 7→ (e, v, s) by Definition 9 with (10, 16, 11, 15, 13, 14)(18) · | Γ1, a : defδ(τ),Γ2 ` S2, a 7→ (e, v, s),S1 by Definition 9 with (17)

S[a 7→ (e, v, s)] = S2, a 7→ (e, v, s),S1 from (8)? Γ ` (S[a 7→ (e, v, s)];P;L@s) by Definition 10 with (18, 4, 6)

(20) CASE: a : varδ(τ)Γ = Γ1, a : varδ(τ),Γ2

(21) S = S2, a 7→ (e, o, s),S1

(22) Γ1 | a : varδ(τ),Γ2 ` S2, a 7→ (e, o, s) by Definition 9 in (3)(23) Γ1, a : varδ(τ) | Γ2 ` S2 by Definition 9 in (22)(24) S2, a 7→ (e, o, s); Γ2 ` [a] by Definition 9 in (22)(25) tS2

(s) ⊆ dom(Γ2) by Definition 9 in (22)(26) S2, a 7→ (e, v, s); Γ2 ` [a] by Definition 7 and (24)(27) Γ1 | a : varδ(τ),Γ2 ` S2, a 7→ (e, v, s) by Definition 9 with (6, 23, 26, 25)(28) · | Γ1, a : varδ(τ),Γ2 ` S2, a 7→ (e, v, s),S1 by Definition 9 with (27)

S[a 7→ (e, v, s)] = S2, a 7→ (e, v, s),S1 from (21)? Γ ` (S[a 7→ (e, v, s)];P;L@s) by Definition 10 with (28, 4, 6)

7. RDO(H1) Γ ` (S;do e,P; [ ])(H2) (S;do e,P; [ ]) −→ (S;do e′,P; [ ])

(3) · | Γ ` S by Definition 10 in (H1)(4) Γ ` do e,P by Definition 10 in (H1)(5) S; Γ ` [ ] by Definition 10 in (H1)(6) S; e −→ e′ by inv. of RDO in (H1)(7) Γ; δ ` e : Action by inv. of DO in (4)(8) Γ ` P by inv. of DO in (4)(9) Γ; δ ` e′ : Action by Lemma 5 with (7, 6)

(10) Γ ` do e′,P by DO with (9, 8)? Γ ` (S;do e′,P; [ ]) by Definition 10 with (3, 10, 5)

8. RSKIP(H1) Γ ` (S;doaction { · },P; [ ])(H2) (S;doaction { · },P; [ ]) −→ (S;P; [ ])

(3) Γ ` doaction { · },P by Definition 10 in (H1)(4) Γ ` P by inv. of DO in (3)(5) · | Γ ` S by Definition 10 in (H1)(6) S; Γ ` [ ] by Definition 10 in (H1)

? Γ ` (S;P; [ ]) by Definition 10 with (5, 4, 6)

Lemma 1 (Queue Convergence). For all configurations (S;P;L) and (S ′;P ′;L′), and typing environmentsΓ, if Γ ` (S;P;L) and L 6= [ ] then (S;P;L) −→∗ (S ′;P ′;L′) and mS (L′) < mS (L).

Proof. By induction on the structure of (S;P;L).1. RVAR

(H1) Γ ` (S;var a = e,P; [ ])(S;var a = e,P; [ ]) −→ (S ′[a 7→ (e,�, s)];P; [a]) by RVAR

? Trivially true because L = [ ]

2. RDEF(H1) Γ ` (S;var a = e,P; [ ])

(S;var a = e,P; [ ]) −→ (S ′[a 7→ (e,�, s)];P; [a]) by RDEF? Trivially true because L = [ ]

3. RASSIGN(H1) Γ ` (S;var a = e,P; [ ])

(S;var a = e,P; [ ]) −→ (S ′[a 7→ (e,�, s)];P; [a]) by RASSIGN

26 2014/6/9

Page 27: Type-Safe Evolution of Data-Centric Applicationsmiguel.domingues.pt/docs/techreport-2014.pdf · Which means that applications may evolve without any service dis-ruption. We use a

? Trivially true because L = [ ]

4. RQEXP(H1) Γ ` (S[a 7→ (e, o, s)];P; a::L)

(S[a 7→ (e, o, s)];P; a::L) −→ (S[a 7→ (e, o, s)];P; a〈e〉::L) by RQEXP(2) mS (a::L) = 1 +mS (a) +mS (L) by Definition 13(3) mS (a〈e〉::L) = mS (a) +mS (L) by Definition 13

? mS (a〈e〉::L) < mS (a::L) from (2, 3)

5. RQSTEP(H1) Γ ` (S[a 7→ (e, o, s)];P; a〈e′〉::L)(H2) S; e′ −→n v Assuming expression termination

(3) (S[a 7→ (e, o, s)];P; a〈e′〉::L) −→n (S[a 7→ (e, o, s)];P; a〈v〉::L) by RQSTEP with (H2)(4) (S[a 7→ (e, o, s)];P; a〈v〉::L) −→ (S[a 7→ (e, v, s)];P;L@s) by RQVAL

(S[a 7→ (e, o, s)];P; a〈e′〉::L) −→∗ (S[a 7→ (e, v, s)];P;L@s) from (3, 4)(5) mS (a〈e′〉::L) = mS (a) +mS (L) by Definition 13(6) mS (a) = 1 +

∑s1∈smS (si) = 1 +mS (s) by Definition 13

(7) mS (a〈e′〉::L) = 1 +mS (s) +mS (L) from (5, 6)(8) mS (L@s) = mS (L) +mS (s) by Definition 13

? mS (a〈e′〉::L) < mS (L@s) from (7, 8)

6. RQVAL(H1) Γ ` (S[a 7→ (e, o, s)];P; a〈v〉::L)

(S[a 7→ (e, o, s)];P; a〈v〉::L) −→ (S[a 7→ (e, v, s)];P;L@s) by RQVAL(2) mS (a〈v〉::L) = mS (a) +mS (L) by Definition 13(3) mS (a) = 1 +

∑s1∈smS (si) = 1 +mS (s) by Definition 13

(4) mS (a〈v〉::L) = 1 +mS (s) +mS (L) from (2, 3)(5) mS (L@s) = mS (L) +mS (s) by Definition 13

? mS (a〈v〉::L) < mS (L@s) from (4, 5)

7. RDO(H1) Γ ` (S;do e,P; [ ])

(S;do e,P; [ ]) −→ (S;do e′,P; [a]) by RDO? Trivially true because L = [ ]

8. RSKIP(H1) Γ ` (S;doaction { · },P; [ ])

(S;doaction { · },P; [ ]) −→ (S;P; [ ]) by RSKIP? Trivially true because L = [ ]

27 2014/6/9