
Advanced Join-Patterns for the Actor Model based on CEP Techniques Humberto Rodríguez Avila, Joeri De Koster, Wolfgang De Meuter Technical Report October 26, 2020 Vrije Universiteit Brussel Faculty of Sciences and Bio-engineering Sciences Department of Computer Science Software Languages Lab 2 Chapter 1 NEST: Formal Semantics and Implementation This chapter presents NEST: a formal calculus for Sparrow. NEST serves as a precise definition of the semantics of core Sparrow abstractions. We start, in Section 1.1, by describing its syntax and operational semantics. Later, in Section 1.1.4, we list the differences between the formal seman- tics of NEST and the current implementation of Sparrow. Finally, in Section 1.2, we present an implementation of the small-step operational semantics of NEST in PLT Redex. 1.1 Operational Semantics This section starts by defining the syntax of NEST (Section 1.1.1) and its main semantic entities (Section 1.1.2). Next, it introduces a set of re- duction rules which represent the core features supported by NEST (Sec- tion 1.1.3). 1.1.1 Syntax Figure 1.2 lists the abstract syntax of NEST, which is composed of three main syntax subsets. The first one, Ps, describes the definition of all dif- ferent types of patterns supported by Sparrow. Notice that pn represent the name of the pattern, and p is used as a holder for the non-terminal expression <pattern> of Figure 1.1. The second subset, Rs, describes the definition of reaction functions. A reaction function has a name ra and a 3 CHAPTER 1. NEST: FORMAL SEMANTICS AND IMPLEMENTATION <pattern> := <elem-pattern> [(and| or ) <elem-pattern>]* [<guard>] [, [options: <option> +]] <elem-pattern> := [not] <selector> [[<operator>+]]{|> <transformer>}* <selector> :={<symbol>, <attribute>*} | <identifier>[{{<inline-guard> | <alias-op> }+}] <attribute> := <value> | <symbol> | <logic-var> <guard> := when <expression> <inline-guard> := <identifier>= <expression> <alias-op> := <identifier> ∼> <identifier> <symbol> :=:<identifier> <logic-var> := [(@|! )]<identifier> <operator> := window: <time> | debounce: <time> | every: <number> | count: <number> <transformer> := fold(<expression>, <expression>) | bind(<identifier>) <option> := seq: <boolean> | interval: <time> | last: <boolean> <time> :={<number>,(:secs| :mins| :hours| :days| :weeks)} Figure 1.1: EBNF-styled grammar for the Sparrow’s pattern language. Ps ⊆ Pattern ::= pattern pn as p Rs ⊆ Reaction ::= reaction rn do e As ⊆ Actor ::= actor an {react_to pn with: rn} e ∈ E ⊆ Expr ::= x | l | i | nil | λx.e | {mid, e} | let x = e in e | spawn an | send e, e | react_to pn, with: rn | remove rn, from: pn | remove_reactions pn x, l, i ∈ VariableName, pn ∈ PatternName, rn ∈ ReactionName, an ∈ ActorName Figure 1.2: Abstract syntax of NEST. 4 1.1. OPERATIONAL SEMANTICS body e. The body of a reaction has access to three implicit arguments: a list of matched messages, a list of intermediate results, and the cur- rent state of the actor. Reactions like patterns are second-class entities. The lockup of both abstractions, as well as their binding (association), is globally scoped within an actor. The third subset, As, describes how to define new actors. The actor construct receives two arguments: the actor name an, and a set of bindings between patterns and reactions previously defined. Finally, the above subsets are glued together by expressions e supported by their base language together with a set of built-in functions. The built-in function react_to with: binds a pattern with name pn to a reaction with name rn. Reactions are executed in the same order they were added to a pattern. The remove from: function unbinds a reaction with name rn from a pattern with name pn. In contrast, remove_reactions remove all reaction associated to a pattern with name pn. After the def- inition of an actor, it can be initialized using the spawn primitive. This function takes a single argument, the actor name an, and return the id (aid) of the new spawned actor. Finally, lambdas are denoted by λx.e, and they correspond to standard Elixir anonymous functions. In addition, lo- cal variables can be introduce via let x = e in e. K ∈ Configuration ::= A Configurations a ∈ A ⊆ Actor ::= Ahaid, Q, (pn, rn), ei Actors M, L ∈ MessageList ::= {mid, v} List of Messages v ∈ Value ::= nil | aid Values I ⊆ IntResult ::= v | (x, v) Intermediate Results e ∈ E ⊆ Expr ::= ... | aid Runtime Expressions aid ∈ ActorId, mid ∈ MessageId, x ∈ VariableName, Figure 1.3: Semantic entities of NEST. 1.1.2 Semantic Entities Figure 1.3 shows the semantic entities of NEST. We use different font styles to distinguish our semantic entities syntactically. For example, the calligraphic letter A represent a constructor. Regular uppercase letters like K and M denote sets or sequences. Parentheses represent a pair, 5 CHAPTER 1. NEST: FORMAL SEMANTICS AND IMPLEMENTATION while curly brackets denote a tuple like in Erlang and Elixir. Actors and messages have different types of identifiers (or ids for short), denoted aid and mid respectively. The state of a NEST program is represented as a configuration K, which is composed of a set running actors. Each actor consists of an identifier aid, a queue Q of messages to be processed, a set of pattern- reaction bindings (pn, rn), and an expression e that is currently evaluated. NEST inherits all primitive values supported by Elixir. To keep simple our semantics those values are not included in our definition, instead only those used by our reduction rules are included (e.g., nil, aid). Messages are represented as Elixir tuples where the first element aid denotes the type of a message, and a list of values v follows it. Intermediate results of pattern transformations I are represented as a set of values v or pairs x, v. The first element of a pair corresponds to a variable’s name and the second to its value. These variables can be used in guard expressions, and they are also accessible in the body of a reaction. Finally, the subset of expressions e is extended to include actor identifiers aid since a sub- expression may reduce to an actor identifier before being reduced further. This new subset of expressions is called runtime expressions, and they are the base operation of our reduction rules 1.1.3 Reduction Rules 1.1.3.1 Evaluation Contexts NEST uses evaluation contexts [FFF09] to determine which subexpres- sions of an expression should be fully reduced before the computation rules can further reduce the compound expression itself. e ::= | let x = e in e | {mid, v, e, e} | send(e, e) | send(e, e) e denotes an expression with a hole. Each occurrence of e announces to our computation rules about an expression with a possible hole. A hole has the purpose of identifying the next subexpression to reduce in a compound expression. We use the notation e[e] indicates that the expression e is part of a compound expression e. As a consequence, our computation rules should reduce such expression e before they reduce further the compound expression e. 6 1.1. OPERATIONAL SEMANTICS 1.1.3.2 Notation We use the following notation conventions to facilitate the understanding of NEST evaluations rules. The notation O = O0 · O00 concatenate two sequences or lists. Sometimes, we also use O = O0 · o as a shortcut to concatenate two lists, in this particular case o is considered as a list with a single element. At the same time, we use a similar notation to decon- structs a sequence being part of the arguments of an auxiliary function. For example, we use the notation o · O and O · o to remove the first or last element respectively from the sequence O. We represent queues as sequences of messages that are processed right-to-left, meaning that the last message in the sequence is the first to be processed. We use the ∅ symbol to denote both empty sets and empty sequences. 1.1.3.3 Evaluation Rules NEST semantics is defined in terms of a relation on configurations, K → K0. Its evaluations rules are split into two parts to make explicit which actions can be executed in isolation by a single actor (local-rules), and which ones require interaction between different actors of a configuration (global-rules). The above rules can be applied non-deterministically, which gives rise to concurrency. NEST does not yet consider actors distributed across different devices; it relays on the default behaviour of the base actor language to handle disconnections. In other words, NEST considers all actors to remain permanently connected. A NEST program is an expression e that is reduced in an initial con- 0 figuration containing a single “root” actor Kinit = {Ahaid, ∅, ∅, nili}. The actor’s queue and the pattern-reaction binding list are initially empty. Fig- ure 1.4 outlines the set of substitution rules employed by NEST evaluation rules. Actor-local reduction rules are always initiated after taking the next message from their actor’s message queue. Such a message is then trans- formed into an appropriate expression to evaluate. Finally, that expression is reduced to a value. This process of reducing such a single expression to a value is called a turn Once a turn is completed, the next message is pro- cessed. As actor are single-threaded computation units, it is not possible to suspend a turn and start processing another message in the middle of a reduction. The execution of local rules stops when the message queue of an actor is empty, and it restarts when a new message arrives. If during 7 CHAPTER 1. NEST: FORMAL SEMANTICS AND IMPLEMENTATION [v/x]x0 = x0 [v/x]let x0 = e in e = let x0[v/x]e in [v/x]e [v/x]x = v [v/x]let x = e in e = let x = [v/x]e in e [v/x]nil = nil [v/x]aid = aid [v/x]send e, e = send [v/x]e, [v/x]e [v/x]spawn pn = spawn pn [v/x]react_to pn, rn = react_to pn, rn [v/x]remove rn, from:pn = remove rn, from:pn [v/x]remove_reactions pn = remove_reactions pn Figure 1.4: Substitution rules: x denotes a variable name or the pseudo-variable, v denotes a value.
Details
-
File Typepdf
-
Upload Time-
-
Content LanguagesEnglish
-
Upload UserAnonymous/Not logged-in
-
File Pages15 Page
-
File Size-