dataesr/scientific-paragraphs-categorization huggingface dataset:
Eliom is a dialect of OCaml for Web programming in which server and client pieces of code can be mixed in the same file using syntactic annotations. This allows to build a whole application as a single distributed program, in which it is possible to define in a composable way reusable widgets with both server and client behaviors. Our language also enables simple and type-safe communication. Eliom matches the specificities of the Web by allowing the programmer to interleave client and server code while maintaining efficient one-way server-to-client communication. The Eliom language is both sufficiently small to be implemented on top of an existing language and sufficiently powerful to allow expressing many idioms of Web programming. In this paper, we present a formalization of the core language of Eliom.
Introduction Web programming usually relies on the orchestration of numerous languages and tools. Web pages are written in HTML and styled in CSS. Their dynamic behavior is controlled through client-side languages such as JavaScript or Ac-tionScript. These pages are produced by a server which can be written in about any language: PHP, Ruby, C++. They are produced based on information stored in databases and retrieved using a query language such as SQL. Programmers must not only master these tools, but also keep synchronized the numerous software artifacts involved in a Web site and make them communicate properly. The server must be able to interact with the database, then send the relevant information to the client. In turn, the client must be able to understand the received data, and interact back properly with the server.
Eliom We present Eliom, an extension of OCaml for tierless programming that supports composable and typesafe client-server interactions. Eliom is part of the larger Ocsigen  [12, 4]  project, which also includes the compiler js_of_ocaml  [24] , a Web server, and various related libraries to build client-server applications. Besides the language presented here, Eliom comes with a complete set of modules, for server and/or client side Web programming, such as RPCs; a functional reactive library for Web programming; a GUI toolkit  [16] ; a powerful session mechanism, to manage the server side state of a Web applications on a per-tab, per-browser, or per-user basis; an advanced service identification mechanism  [2] , providing a way to implement traditional Web interaction (wellspecified URLs, back button, bookmarks, forms,.
A core language for tierless web programming All of the modules and libraries implemented in Ocsigen, and in particular in the Eliom framework, are implemented on top of a core language that allows to express all the features needed for tierless web programming. Composition. Eliom encourages the building of independent and reusable components that can be assembled easily. It allows to define and manipulate on the server, as first class values, fragments of code which will be executed on the client. This gives us the ability to build reusable widgets that capture both the server and the client behaviors transparently. It also makes it possible to define libraries and building blocks without explicit support from the language. Leveraging the type system. Eliom introduces a novel type system that allows composition and modularity of client-server programs while preserving typesafety and abstraction.
Explicit communication. Communication between the server and the client in Eliom is always explicit. This allows the programmer to reason about where the program is executed and the resulting trade-offs. The programmers can ensure that some data stay on the client or on the server, or choose how much communication takes place and where computation is performed. A simple and efficient execution model. Eliom relies on a novel and efficient execution model for client-server communication that avoids constant back-andforth communication. This model is simple and predictable. Having a predictable execution model is essential in the context of an impure language, such as ML. These four properties leads us to define a core language, Eliom ε , that features all these characteristics, while being small enough to be reasoned about in a formal way.
Having a small core language into which more complex constructs can be reduced has several advantages. First, it is sufficient to trust the core language. All the desirable properties about the core language will also be valid for the higher-level abstractions introduced later. A minimal core language also makes the implementation on top of an existing language easier. In the case of Eliom, it allows us to implement our extension on top of the existing OCaml compiler with a reasonably small amount of changes. By extending an existing language, we gain the ability to use numerous preexisting libraries: cooperative multitasking  [23] , HTML manipulation  [22]  and database interaction  [20]  are all provided by libraries implemented in pure OCaml that we can leverage for Web programming, both server and client side.
How to: client-server Web programming An Eliom application is composed of a single program which is decomposed by the compiler into two parts. The first part runs on a Web server, and is able to manage several connections and sessions at the same time, with the possibility of sharing data between sessions, and to keep state for each browser or tab currently running the application. The client program, compiled statically to JavaScript, is sent to each client by the server program together with the HTML page, in response to the initial HTTP request. It persists until the browser tab is closed or until the user follows an external link. Eliom is using manual annotations to determine whether a piece of code is to be executed server or client side  [3, 1]. This choice of explicit annotations is motivated by the fact that we believe that the programmer must be well aware of where the code is executed, to avoid unnecessary remote interactions.
Examples We show how these language features can be used in a natural way to build HTML pages with dynamic behavior in a composable fashion. More detailed examples are available on the Ocsigen website  [12]. Increment button. We can define a button that increments a client-side counter and invokes a callback each time it is clicked. We use a DSL to specify HTML documents. The callback action is a client function. The state is stored in a client-side reference. The onclick button callback is a client function that modifies the references and then calls action. This illustrates that one can define a function that builds on the server a Web page fragment with a client-side state and a parametrized client-side behavior. It would be straightforward to extend this example with a second button that decrements the counter (sharing the associated state).
Libraries These examples show how to build reusable widgets that encapsulate both client and server behavior. They also showcase some of the libraries that are provided with Eliom. In contrast to many Web programming languages and frameworks, which provides built-in constructions, all these libraries have been implemented only with the primitives presented in this paper. Using fragments and injections along with converters, which are presented later, we can implement numerous libraries such as remote procedure calls, client-server HTML or reactive programming directly inside the language, without any compiler support.
Client-server communication In the examples above, we showcased complex patterns of interleaved client and server code, including passing client fragments to server functions, and subsequently to client code. This would be costly if the communication between client and server were done naively. Instead, a single communication takes place: from the server to the client, when the Web page is sent. This is made possible by the fact that client fragments are not executed immediately when encountered inside server code. The intuitive semantics is the following: client code is not executed right away; instead, it is registered for later execution, once the Web page has been sent to the client. Then all the client code is executed in the order it was encountered on the server. This intuitive semantics allows the programmer to reason about Eliom programs, especially in the presence of side effects, while still being unaware of the details of the compilation scheme.
Syntax In order to clearly distinguish server code from client code, we use subscripts to indicate the location where a piece of syntax belongs: a 's' subscript denotes server code, while a 'c' subscript denotes client code. For instance, e s is a server expression and τ c is a client type. We also use 'ς' subscripts for expressions which are location-agnostic: they can stand for either s or c. When the location is clear from the context, we omit the subscripts. The syntax is presented in Figure  1. It follows the ML syntax, with two additional constructs for client fragments and injections respectively. [26]  was used as a base for the elaboration of Eliom ε. The language is parametrized by its constants. There are different sets of constants for the server and for the client: Const s and Const c.
Type system The type system of Eliom ε is an extension of the regular ML type system. We follow closely  [26]. Again, the language is split into a client and a server part. σ ς ::= ∀α *. τ ς (TypeSchemes) τ s ::= α | τ s → τ s | {τ c } | τ s τ c | κ for κ ∈ ConstType s τ c ::= α | τ c → τ c | κ for κ ∈ ConstType c (Types) ConstType ς is the set of ground types. Two server-side types are added to core ML types: {τ c } is the type of a client fragment whose content is of type τ c ; τ s τ c is the type of converters from server type τ s to client type τ c. This last type is described in more details below. No client-side are added to core ML types: in particular, the type of a client expression can never contain the type of a client fragment {τ c }. The typing rules are presented in Figure  2.
We assume the existence of two built-in converters: -The serial converter of type serial serial. Both sides are the identity. -The fragment converter of type ∀α. ({α} α). Note that this type scheme can only be instantiated with client types. Type universes It is important to note that there is no identity converter (of type ∀α. (α α)). Indeed the client and server type universes are distinct and we cannot translate arbitrary types from one to the other. Some types are only available on one side: database handles, system types, JavaScript API types. Some types, while available on both sides, are simply not transferable. For example, functions cannot be serialized. Finally, some types may share a semantic meaning, but not their actual representation. This is the case where converters are used.
For example, integers are often 64-bit on the server and are 32-bit in JavaScript. So, there is an int s and an int c type, along with a converter of type int s int c. Another example is an HTTP endpoint. On the server, it is a URL together with a function called when the endpoint is reached. On the client, it is only the URL of the specified endpoint. These two types are distinct but share the same semantic meaning, and a converter relates them. Implementation of converters Specifying which converter to use for which injection is quite tedious in practice. The current implementation of Eliom uses runtime information to discover which converter to apply. A better implementation would use ad-hoc polymorphism, such as modular implicits  [25]  or type classes, to define converters.
The queue is a first-in, first-out data structure. We note + + the concatenation on queues. Substitute of a variable by a value in an expression or a program is noted e[v/x]. Eliom ε is eager and call by value. Evaluation contexts are shown in Figure  3. Injections are rewritten inside client expressions. The location where this can take place is specified by context C[e c ] below. We write e c for a client expression containing no injection. Thus, we are forcing a left to right evaluation inside client fragments. The evaluation context for expressions E ς [e ς ] is standard, except that, we also evaluate server expressions in injections f %e s inside client code. Program contexts F [e ς ] specifies that the evaluation can take place either in a server declaration or in server code deep inside injections.
The primitive encode returns the server side encoding function of a converter; the primitive decode returns a reference to a client fragment implementing the client side decoding function of a converter. The serial and fragment converters are basically the identity, so they are erased once the value to be transferred has been computed (rules Serial s and Serial c ). Once all the server declarations have been executed, the expressions in ξ are executed in the same order they were encountered prior in the evaluation (rules Exec, Context and Bind). This means that the execution of an Eliom ε program can be split into two phases: server-side execution, then client-side ex- App (λx. eς ) vς | ξ -→ eς [vς /x] | ξ Y Y vς | ξ -→ vς (λx. (Y vς ) x) | ξ Let let x = vς in eς | ξ -→ eς [vς /x] | ξ Delta δς (cς , vς ) is defined (cς vς ) | ξ -→ δς (cς , vς ) | ξ Server semantics Converters f / ∈ {serial, fragment} {{ C[f %es] }} | ξ -→ s {{ C[fragment%(decode f ) serial%((encode f ) es)] }} | ξ Serials f ∈ {serial, fragment} {{ C[f %v] }} | ξ -→ s {{ C[v] }} | ξ ClientFragments r fresh {{ e c }} | ξ -→ s r | ξ + + [r → e c ] Eliomε's semantics This semantics is not equivalent to immediately executing every piece of client code when encountered: the order of execution would be different.
Compilation to client and server languages In a more realistic computation model, different programs are executed on the server and on the client. We thus present a compilation process that separates the server and client parts of Eliom programs, resulting in purely server-side and client-side programs. We express the output of the compiler in an ML-like language with some specific primitives for both sides. The further compilation of these ML-like languages to machine code for the server, and to JavaScript for the client  [24]  is out of the scope of this paper.
From Eliom ε to ML ε Before introducing the exact semantics of these primitives, we specify how Eliom ε is translated using these primitives, which will make their behavior clearer. A key point is that we adopt a distinct compilation strategy for client declarations and for client fragments. Indeed, client declarations are much simpler than client fragments, as they are executed only once and immediately. Their code can be used directly in the client, instead of relying on a sophisticated mechanism. The rewriting function ρ from Eliom ε to ML ε can be split into two functions ρ s and ρ c , respectively for server and client code. For each case, we first decompose injections f %e s into an equivalent expression: fragment%(decode f ) serial%(encode f e s ) Translating client declarations is done by taking the following steps: -For each injection fragment%e s or serial%e s , we generate a fresh name x.
-In ML s , the primitive "injection x e s " is called for each injection; it signals that the value of x should be transmitted to the client. -In ML c , we replace each injection fragment%e s or serial%e s by x. An example is presented Figure  7. On the server, the return value of the program is always () since the server program never returns anything. The client program returns the same value as the Eliom ε one. The reference to the client fragment implementing the decoder is associated to variable conv_int, to be transmitted and used by the client to decode the value. Translating server declarations containing client fragments is a bit more involved. We need to take care of executing client fragments on the client. -For each client fragment {{ e }} containing the injections f i %e i , we create a fresh reference f.
A more detailed presentation of the translation rules are given in Appendix A. Eliomε MLs MLc lets x = {{ 1 }} in lets y = {{ fragment%x + 1 }} in. let x = fragment f 0 [ ] in end (); let y = fragment f 1 [x] in end ();. bind f 0 = λ(). 1 in exec (); bind f 1 = λx. (x + 1) in exec ();. We need to guarantee that the translation from Eliom ε to the two languages two languages, ML s and ML c is faithful. Some additional properties that gives a better insight into the execution of Eliom ε programs are given in Appendix B. 1. Since Eliom ε is parametrized by its constants, the functions δ, Const and TypeOf must satisfy a typability condition for the language to be sound.
Hypothesis 1 (δ-typability). For ς in {c, s}, if TypeOf ς (c) τ → τ and ς v : τ then δ ς (c, v) is defined and ς δ ς (c, v) : τ We extend the typing relation to account for the execution queue ξ. The judgment ξ, p : τ states that, given the execution queue ξ, the program p has type τ. We also introduce an judgment Γ ξ : Γ to type execution queues, where the environment Γ extends Γ with the types of the bindings in ξ. We introduce the following typing rules. The rule Queue tells us that if we can type a queue, producing an environment Γ , and we can type a program p in this environment, then we can type the pair of the queue and the program. This allows us to type a program during its evaluation, and in particular when the queue is no longer empty since the rule ClientValue has been applied.
Assuming the δ-typability hypothesis, we can now gives the following two theorem. This guarantees that the semantics of Eliom ε can be used to reason about side effects and evaluation behaviors in compiled Eliom ε programs. A more precise statement can be seen in Appendix B. 2 Theorem 1 (Subject Reduction). If ξ 1 , p 1 : τ and p 1 | ξ 1 - → p 2 | ξ 2 then ξ 2 , p 2 : τ. Theorem 2 (Simulation). Let p be an Eliom ε program with an execution p | ∅ -→ * v | ∅ For an execution of p that terminates, we can exhibit a chained execution of ρ s (p) and ρ c (p) such that evaluation is synchronized with p.
Related work Unified client-server languages Various directions have been explored to simplify Web development and to adapt it to current needs. Eliom places itself in one of these directions, which is to use the same language on the server and the client. Several unified client-server languages have been proposed. They can be split in two categories. JavaScript can be used on the server, with Node. js; it can be used as a compilation target: for instance, Google Web Toolkit for Java or Emscripten for C. The approach of compiling to JavaScript was also used to develop new client languages aiming to address the shortcomings of JavaScript. Some of them are new languages, such as Haxe, Elm or Dart. Others are simple JavaScript extensions, such as TypeScript or CoffeeScript. These various proposals do not help in solving client-server communication issues: the programmer still writes the client and server code separately and must ensure that messages are written and read in a coherent way.
Tierless languages and libraries Several other languages share with Eliom the characteristic of mixing client and server code in an almost transparent way. We will first give a high-level comparison of the various trade-offs involved. In Eliom, code location is indicated by manual annotations. Several other approaches infer code location using known elements (database access is on the server, dynamic DOM interaction is done on the client, etc) and control flow analysis  [18, 17, 9]. This approach presents various difficulties and drawbacks: It is extremely difficult to integrate to an existing language; it is difficult to achieve with an effectful language; the slicing cannot be as precise as explicit annotations. For example it will not work if the program builds datastructures that mix client fragments and other data, as shown in Section 2.
4. We believe that the efficiency of a complex Web application relies a lot on the programmer's ability to know exactly where the computation is going to happen at each point in time. In many cases, both choices are possible, but the result is very different from a user or a security point of view. Eliom has two type universes for client and server types (see Section 3. 2). This allows the type system to check which functions and types are usable on which side. Most other systems do not track such properties at the type level. Eliom uses asymmetric communication between client and server (see Section 3. 3). Most other languages provide only two-way communications. The actual implementation of Eliom also provides two-way communications as a library, allowing the user to use them when appropriate.
We now provide an in-depth comparison with the most relevant approaches. Ur/Web  [8, 7]  is a new statically typed language special purposed for Web programming. While similar in scope to Eliom, it presents a very different approach: Ur/Web uses whole-program compilation and a global automatic slicing to separate client and server code. This makes some examples hard to express, such as the one in Section 2. 4. Client and server locations are not tracked by the type system and are not immediately visible in the source code, which can make compiler errors hard to understand, and is incompatible with separate compilation. Furthermore and contrary to Eliom, several primitives such as RPC are hardcoded in the language. Hop  [21, 6]  is a dialect of Scheme for programming Web applications. Like Eliom it uses explicit location annotations and provide facilities to write complex client-server applications.
However, as a Scheme-based language, it doesn't provide static typing. In particular, contrary to Eliom, Hop doesn't enforce statically the separation of client and server universes (such as using database code inside the client). Links  [10]  is an experimental functional language for client-server Web programming with a syntax close to JavaScript and an ML-like type system. Its type system is extended with a notion of effects, allowing a clean integration of database queries in the language. It doesn't provide any mechanisms to separate client and server code, so they are shared by default, but uses effects to avoid erroneous uses of client code in server contexts (and conversely). Compared to Eliom, compilation is not completely available and Links doesn't provide an efficient communication mechanism.
Haste  [11]  is an extension of Haskell similar to Eliom. Instead of using syntactic annotations, it embeds client and server code into monads. This approach works well in the Haskell ecosystem. However Haste makes the strong assumption that there exists a universe containing both client and server types, shared by the client and the server. Eliom, on the contrary, doesn't make this assumption, so the monadic bind operator for client fragments, of type ('a -> { 'b })-> { 'a } -> { 'b }, makes no sense: 'a would be a type both in the server and the client, which is not generally true. Meteor. js  [15]  is a framework to write both the client and the serve side of an application in JavaScript. It has no built-in mechanism for sections and fragments but relies on if statements on the Meteor. isClient and Meteor.
Conclusion We have presented a formalization of the core language Eliom ε , a client-server Web application programming language. First, we have given a formal semantics and a type system for a language that contains the key features of Eliom. This semantics is intuitive and easy to understand. It corresponds to what a programmer needs to know. Then, we have defined a lower level semantics, corresponding to how Eliom is compiled. We then showed how this compilation is done and that it preserves the semantics. Eliom ε is used as a core language for the larger Eliom framework and the Ocsigen ecosystem. Eliom ε is sufficiently small to be reasoned about and implemented on top of an existing language, such as OCaml. It is also expressive enough to allow the implementation, without any additional language built-in constructs, to all kinds of widgets and libraries used for Web programming.