<?xml version="1.0" encoding="UTF-8"?>
<TEI xml:space="preserve" xmlns="http://www.tei-c.org/ns/1.0" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xsi:schemaLocation="http://www.tei-c.org/ns/1.0 https://raw.githubusercontent.com/kermitt2/grobid/master/grobid-home/schemas/xsd/Grobid.xsd"
 xmlns:xlink="http://www.w3.org/1999/xlink">
	<teiHeader xml:lang="en">
		<fileDesc>
			<titleStmt>
				<title level="a" type="main">Transforming Erlang finite state machines</title>
			</titleStmt>
			<publicationStmt>
				<publisher/>
				<availability status="unknown"><licence/></availability>
			</publicationStmt>
			<sourceDesc>
				<biblStruct>
					<analytic>
						<author>
							<persName><forename type="first">Dániel</forename><surname>Lukács</surname></persName>
							<email>dlukacs@caesar.elte.hu</email>
							<affiliation key="aff0">
								<orgName type="institution">ELTE Eötvös Loránd University Faculty of Informatics Budapest</orgName>
								<address>
									<country key="HU">Hungary</country>
								</address>
							</affiliation>
						</author>
						<author>
							<persName><forename type="first">Melinda</forename><surname>Tóth</surname></persName>
							<email>tothmelinda@caesar.elte.hu</email>
							<affiliation key="aff0">
								<orgName type="institution">ELTE Eötvös Loránd University Faculty of Informatics Budapest</orgName>
								<address>
									<country key="HU">Hungary</country>
								</address>
							</affiliation>
						</author>
						<author>
							<persName><forename type="first">István</forename><surname>Bozó</surname></persName>
							<email>bozoistvan@caesar.elte.hu</email>
							<affiliation key="aff0">
								<orgName type="institution">ELTE Eötvös Loránd University Faculty of Informatics Budapest</orgName>
								<address>
									<country key="HU">Hungary</country>
								</address>
							</affiliation>
						</author>
						<title level="a" type="main">Transforming Erlang finite state machines</title>
					</analytic>
					<monogr>
						<imprint>
							<date/>
						</imprint>
					</monogr>
					<idno type="MD5">4843D1840131E0256474C958F0600B2E</idno>
				</biblStruct>
			</sourceDesc>
		</fileDesc>
		<encodingDesc>
			<appInfo>
				<application version="0.7.2" ident="GROBID" when="2023-03-24T00:25+0000">
					<desc>GROBID - A machine learning software for extracting information from scholarly documents</desc>
					<ref target="https://github.com/kermitt2/grobid"/>
				</application>
			</appInfo>
		</encodingDesc>
		<profileDesc>
			<abstract>
<div xmlns="http://www.tei-c.org/ns/1.0"><p>Model driven development approaches help to alleviate the abstraction gap between high-level design and actual implementation, to aid design, development and maintenance of industrial scale software systems. To provide automatic, easily usable tools for stakeholders, model driven development essentially relies on efficient and expressive translations between the program source code and the model.</p><p>We present a declarative, rule-based approach to deterministically transform Erlang program sources that satisfy a certain syntactical constraint, into valid UML models of state machines. The transformation relies only on static analysis techniques, and the produced model conforms to the state machine metamodel defined in OMG UML 2.0.</p></div>
			</abstract>
		</profileDesc>
	</teiHeader>
	<text xml:lang="en">
		<body>
<div xmlns="http://www.tei-c.org/ns/1.0"><head n="1">Introduction</head><p>In industrial settings there is an always present necessity to use large software applications with over millions of lines of source code. During design, development and maintenance of software, managing the complexity emerging from these large volumes becomes a critical issue in order to realise a successful product lifecycle. The most important resource needed to manage complexity is relevant, up-to-date information, commonly manifested as the design, development and user documentations. As the software evolves during its development and usage, documentations also have to be actualised to mirror the collective knowledge that was incorporated in the system during its changes. To implement this resource intensive process with the highest efficiency, organisations concerned with software development employ various automatic software analysis tools and machine processable documents to support the developers in creating documentations and keeping them up to date. These tools can also be extremely useful in cases of undocumented legacy systems, where maintainers have to collect information about the inner workings of the system from scratch. One of the more successful methodology to develop, analyse, store and process this kind of information is Model Driven Development (MDD) <ref type="bibr" target="#b17">[20]</ref>, which utilises models specified by both human and machine readable documents in order to represent the various aspects of these systems. MDD methodology uses sophisticated software solutions to create these models, and to aid in querying valuable information during the analysis of these models and the system itself.</p><p>In this paper, we concern ourself with state machine models, that can be used to model event-driven systems. Specifically, we introduce here a method to generate formal UML <ref type="bibr" target="#b4">[7]</ref> state machine models from executable Erlang state machine source code. Formal UML models can be readily transformed into human readable diagrams, they are suited to calculate various model metrics on them, and there exist extensions of UML that can be used to specify executable models <ref type="bibr" target="#b17">[20]</ref>. First, this transformation makes use of the RefactorErl static analysis framework <ref type="bibr" target="#b13">[16,</ref><ref type="bibr" target="#b8">11,</ref><ref type="bibr" target="#b21">24]</ref> to analyse the application source code, then it will transform and synthesise the program representation resulting from the analysis, into an UML state machine model. We specified the transformation by defining an algorithm that utilises backtracking and graph pattern matching of certain sets of transformation rules. To generalise the algorithm, we encapsulated all the RefactorErl specific logic into the transformation rules, thus separating the general operation principles of the method from the implementation specific details. This approach also makes it easier to extend the capability of the algorithm by adding more rules. To test our design in practice we also created a reference implementation, and, as presented in Section 6, used this to successfully transform several Erlang state machines selected from the source code of large, popular, open source Erlang applications.</p><p>The rest of this paper is structured as follows. At first, Section 2 describes UML and Erlang state machines. Sections 3 and 4 introduce the methodology and the transformation rules to generate UML state machines. In Section 5 we explain the transformation starting from an example Erlang source code. Section 6 presents the evaluation of our work on several open source projects. Finally, Sections 7 and 8 present related work and conclude the paper.</p></div>
<div xmlns="http://www.tei-c.org/ns/1.0"><head n="2">Background</head><p>One way to represent the execution history of a computer program is to take snapshots of the state of the program memory. State machines can be used to abstract away this low level representation. With state machines these memory snapshots are taken upon the occurrence of certain events, and instead of storing the content of the memory, we just store descriptive labels, called states. Therefore, a state describes a segment of the program behaviour, while a state transition describes a change in such behaviours, usually triggered by an event <ref type="bibr" target="#b18">[21]</ref>.</p><p>2.1 Our target metamodel: UML state machines Among many others, Unified Modeling Language (UML) <ref type="bibr" target="#b4">[7]</ref> is one of the more accepted standards to represent state machines. UML itself is a family of various languages (metamodels) suitable to represent various aspects of large software systems. The UML state machine language can be used to formally describe event-driven systems, i.e. systems that wait for certain events, and upon the occurrence of these events, they change their behaviour and wait for a possibly different set of events. The state machine metamodel of UML is a more general representation of computation than the classical models of finite state machines, since it provides several extensions to the classical model, like embedded state machines, assignable variables, branching states with guards, etc.</p><p>Figure <ref type="figure">1</ref> depicts the UML state machine language with a metamodel diagram. The root container object is always an instance of the StateMachine class. The root object contains a Region object, which in turn contains Vertex and Transition objects, that can be used to denote states and state transitions respectively. Pseudostate vertices can be used to denote initial states and choice states, FinalState vertices to denote stop states, and State vertices to denote ordinary states. The transitions can be assigned events (Trigger), guards (Constraint) and actions (Behavior).</p></div>
<div xmlns="http://www.tei-c.org/ns/1.0"><head n="2.2">State machines in the Erlang language</head><p>Erlang <ref type="bibr" target="#b9">[12,</ref><ref type="bibr" target="#b11">14]</ref> is a general purpose, functional, dynamically typed, open source programming language, mostly used to develop multithreaded, real time, fault tolerant applications, like telecommunication systems, web servers, or distributed databases. The language provides various abstractions to support these applications. For example, the event handler (gen event), thread monitor (supervisor), server (gen server), and state machine (gen fsm) behaviours, provided by the built-in OTP library <ref type="bibr" target="#b14">[17,</ref><ref type="bibr" target="#b11">14]</ref>. Behaviours have similar roles to abstract classes in the object oriented paradigm: to implement a behaviour, we have to implement certain functions, called callback functions, specified by the behaviour semantics. The complex, behaviour specific background logic connecting these callbacks together is provided by Erlang. This way, we only have to implement the logic specific to our application, but not the logic specific to the behaviour semantics. For example, the requirements of the gen fsm behaviour are to implement a callback function, named init, and any number of transition functions. The function init will designate, at a minimum, the initial state of the state machine. The transition functions will designate, at a minimum, the next state the state machine will be in when it receives a specific event, while in a specific state. All the logic necessary to handle multiple threads, messages, events, etc. will be handled by Erlang in accordance to the gen fsm semantics <ref type="bibr" target="#b11">[14]</ref>.</p><p>Figure <ref type="figure">1</ref>: The UML state machine metamodel <ref type="bibr" target="#b4">[7]</ref> In our research, we use the RefactorErl static analysis framework <ref type="bibr" target="#b8">[11,</ref><ref type="bibr" target="#b21">24]</ref> to analyse Erlang source code. The RefactorErl tool first analyses the source code, and then stores the discovered lexical, syntactic and semantic information in a database. This information can be accessed through various user interfaces, and the framework provides several feature to run refactorings on the source code, to perform further analyses -like data flow, and dynamic function call analysis -, to execute various queries, to calculate certain metrics, and many other features. To transform Erlang state machines to UML state machines, we based our definition of the transformation on the data structure RefactorErl uses to represent the lexical, syntactic and semantic information it gathers. This data structure will be described in more detail in Section 3.</p></div>
<div xmlns="http://www.tei-c.org/ns/1.0"><head n="3">Methodology</head><p>In this section we first describe the main entities and their related notations involved in the transformation of Erlang state machines (i.e. Erlang modules implementing the gen fsm behaviour), and then we give the algorithm that realises this transformation.</p></div>
<div xmlns="http://www.tei-c.org/ns/1.0"><head n="3.1">Internal program representation of RefactorErl</head><p>The RefactorErl analysis framework stores all information it gathers about Erlang programs via static analysis in a special data structure, called semantic program graph (SPG) <ref type="bibr" target="#b8">[11]</ref>. In this paper, we show how the SPG can be transformed into a state machine, which corresponds to the original state machine described by the original Erlang source code. As the SPG is based on a syntax tree and extended with various semantic elements, it represents the lexical, syntactic and semantic structure of one or more Erlang applications. Syntactic and Figure <ref type="figure">2</ref>: A simpler metamodel for describing abstract state machines semantic elements of a program are mapped to nodes in this graph, while their relationships are mapped to edges between the corresponding nodes. In the following sections the set of all nodes in a specific SPG instance will be denoted as V SP G , while set of all edges will be denoted as E SP G .</p><p>A small Erlang program and a segment of its SPG can be observed in Figure <ref type="figure">3</ref> and Figure <ref type="figure" target="#fig_6">4</ref> in Section 5. Apart from the special node called root, all nodes in the SPG correspond to lexical, syntactic, or semantic elements in the Erlang source code. The root node is the only node without incoming edges, and serves as the common ancestor for all nodes of the SPG. Edges of the SPG are ordered.</p><p>RefactorErl supplies various tools for discovering and analysing the SPG, such as a user friendly query language, and several useful library functions that can be used in more complex programmed queries <ref type="bibr" target="#b23">[26]</ref>. Refac-torErl also performs special predefined semantic analyses on the SPG. One of these is the zeroth and first order dataflow analysis that discovers how data can flow between the syntactical elements of an Erlang program and marks these dataflow relations as edges between the corresponding SPG nodes <ref type="bibr" target="#b22">[25,</ref><ref type="bibr" target="#b8">11]</ref>. Another one is dynamic function call analysis that discovers the functions called by dynamic function calls, and represents this relationship with an edge in the SPG between the corresponding function node and the node of the dynamic caller expression <ref type="bibr" target="#b12">[15]</ref>.</p></div>
<div xmlns="http://www.tei-c.org/ns/1.0"><head n="3.2">A simpler metamodel for describing abstract state machines</head><p>In this section we will describe a simple state machine metamodel, depicted by Figure <ref type="figure">2</ref>, with which we represent the target state machines of the transformation. We showed in <ref type="bibr" target="#b16">[19]</ref> that this metamodel (and its instances) can be mapped onto the UML state machine metamodel (and its instances). This intermediate state machine language explicitly highlights the elements we utilise from UML. Later in this section we will introduce a notation for these elements. For implementation purposes, the intermediate state machine can be omitted altogether, by substituting the UML state machine element descriptions for the corresponding elements in our notation.</p><p>The target state machines will basically consist of states (AnyState) and transition (Transition) elements between those states. There are four kinds of states: ordinary states (State), the initial state (InitState), stop states (StopState), and choice states (ChoiceState). Every transition may have exactly one source and one target state. States may have arbitrary number of incoming and outgoing edges, including zero. Transitions may have trigger and guard attributes, depending on whether their source state is an ordinary state or a choice state, respectively. In this paper, triggers and guards will be represented as simple strings constructed from events and guard expressions in the Erlang source code. In order to make the target state machines executable, further research could extend this approach to include a more sophisticated representation for trigger and guard elements. In the following sections the set of all states in a specific state machine instance will be denoted as V F SM G , while the set of all transitions will be denoted as E F SM G .</p><p>Let Init be the following set of gen fsm callback functions: Init def = {init/1, handle event/3, handle sync event/4, handle info/3, code change/4}</p><p>As per the specification of the gen fsm behaviour, the functions in Init, when triggered, can put the state machine in any arbitrary state, independently of the actual state. If we only consider the behaviour of an Erlang state machine in terms of states and transitions, but do not consider the memory changes (side effects) accumulated during the execution, then it can be said that these functions effectively restart the state machine. Therefore, it makes sense to model these as initial states, i.e. states from which the state machine execution can be started.</p><p>To describe the transformation rules we will use a textual notation to denote a mapping from nodes in the SPG and states in the state machine, and also its inverse, a mapping from states to nodes. Since we previously distinguished four types of states, we will use a different function for every type: each of these maps a node to a state with the associated state-type. All these functions can be defined to be invertible.</p><p>• state ∈ V SP G → V F SM G maps nodes to ordinary states. The nodes mapped to ordinary states will precisely be the semantic nodes representing transition functions, i.e. the user defined callback functions of the genfsm behaviour, bearing the name of a state. We chose these nodes, since they have a 1:1 correspondence with the states of the state machine implemented by the analysed Erlang module.</p><p>• choice ∈ V SP G → V F SM G maps nodes to choice states. The nodes mapped to choice states are either representing functions with multiple clauses, or they are representing branching expressions. For brevity, in this paper we only touch upon the latter -and simpler -case: branching expressions. We presented handling of the former case in <ref type="bibr" target="#b15">[18]</ref>.</p><p>• stop ∈ V SP G → V F SM G maps nodes to stop states. Following the specification of the gen fsm behaviour, the nodes mapped to stop states will precisely be those representing tuple expressions, that are return points of a transition function, and have the stop atom as their first element.</p><p>• init ∈ V SP G → V F SM G maps nodes to initial states. Following the specification of the gen fsm behaviour and our previous remark, the nodes mapped to initial states will precisely be those representing the functions in Init.</p><p>After applying the transformation, every state in the target state machine will correspond to a node in the SPG, and every transition in the target state machine will correspond to an edge sequence in the SPG. In Section 4 where we describe the transformation rules we will denote this state-node correspondence relation with the function node : V F SM G → V SP G . The node function is defined as the inverse of the node-state mapping described earlier. Thus, if we regard the earlier functions as relations, i.e. sets of ordered pairs, then</p><formula xml:id="formula_0">node def = (state ∪ choice ∪ stop ∪ init) −1</formula><p>Since the range of these functions are pairwise disjoint, and all four functions were invertible, node always exists.</p><p>In the definition of the transformation rules, we also use a textual notation to denote the trigger and guard labels of the transitions. As mentioned earlier, we represent these as simple human or machine-readable strings. The set of all strings will be denoted by S.</p><p>• trigger ∈ V SP G → S maps nodes representing the first parameter pattern of a transition function to a string.</p><p>For example, the string may consist entirely of the Erlang term denoting this parameter.</p><p>• guard branch , guard if , guard try , guard catch ,guard af ter and guard clause ∈ V n SP G → S functions map nodes representing the pattern and guard expressions of the clauses of the various branching expressions can be found in the Erlang programming language. Since it may be necessary to use more patterns and guard expression to uniquely identify a state machine guard, we assume these functions can handle more parameters. The exact value of n depends only on the guard function it describes.</p></div>
<div xmlns="http://www.tei-c.org/ns/1.0"><head n="3.3">An algorithm for transforming program graphs to state machines</head><p>In this section we present an algorithm, that -with the help of a predefined set of transformation rulestransforms the semantic program graph of any Erlang state machine adhering to the specification of the gen fsm behaviour, to a state machine model described in UML or the simple state machine language we introduced in Section 3. Since most of the application specific logic (the logic related to the RefactorErl semantic program graph) of the transformation are encoded in the transformation rules, the algorithm itself is relatively simple. Basically it is an extended depth first search, that selects the neighbouring nodes to discover, based on predefined rules.</p><p>This approach has several advantages. To extend the transformation for currently unhandled cases, we do not have to modify the procedural algorithm, we only have to add more rules to the transformation sets. For example, UML offers several state machine features (e.g. embedded state machines, variables, effects) that could be utilised by the transformation, after the rule set were to be appropriately extended to handle these cases. Also, the rule sets encapsulate the RefactorErl specific logic, which means we could use the same algorithm with other static analysis frameworks too. We just have to swap the RefactorErl specific rule sets to the rule sets specific to the other static analysis framework. It is worth noting though that devising a rule set, in general, is not a trivial task. Finally, this approach opens up the possibility to execute rules in parallel, to achieve better runtime performance.</p><p>Informally, our transformation algorithm, together with the rules presented in Section 4, will perform the following tasks:</p><p>1. Starting with the transition functions in Init, the algorithm analyses the return point of each transition function it visits.</p><p>2. If during the analysis, it discovers an branching expression or a function with multiple clauses, denoted as b, the corresponding choice(b) choice state will be added to the state machine. Then the algorithm continues by analysing the return points of each clause of the b branching expression or function.</p><p>3. If during the analysis a t tuple is discovered, it will further analysed t to decide whether it indicates a stop state, or an ordinary state. In the former case, the corresponding stop(t) stop state will be added to the state machine, and the algorithm backtracks. In the latter case, it will analyse the appropriate element of t (see the gen fsm specification <ref type="bibr" target="#b11">[14]</ref>), to find out the f name of the target state of the currently analysed transition function. If found, the algorithm will continue to analyse the transition function with name f . 4. For any other node type, the algorithm will proceed in way specific to this node type. In most cases it will utilise the dataflow analysis provided by the RefactorErl tool <ref type="bibr" target="#b22">[25,</ref><ref type="bibr" target="#b8">11]</ref>. Since the dataflow analysis may abstract away information necessary to analyse gen fsm modules, we require node type specific analysis in some cases.</p><p>5. When the algorithm adds an s state to the state machine, it will also have to add an appropriate transition between s and the old state o, which corresponds to the transition function named o, that was analysed as s was discovered.</p><p>More specifically, our algorithm will perform these generic tasks in three separate stages: an analysis stage, a transformation stage, and a synthesis stage. In the analysis stage, our goal is to discover precisely those nodes and edges in the SPG that will be mapped to state machine elements in later stages. The result is a filtered SPG, called the analysed SPG, consisting only these nodes and edges. The edges are relabelled with semantic information about their role in the future state machine. The transformation stage eliminates nodes and edges from this analysed SPG, so as to obtain a reduced SPG that can be mapped to a state machine instance with relative ease. The synthesis stage will map the reduced SPG to a state machine instance, producing the final result of the transformation.</p><p>The general algorithm with the three stages is denoted on Figure <ref type="figure">1</ref>. All three stages will start a depth first algorithm from the function nodes in the Init set or, in the case of the synthesis stage, init(Init), the set of the initial states corresponding to the nodes in Init. For certain edges we will not continue the analysis, i.e. will not extend the target nodes of these edges. The types of these edges are listed in the Exclude 1 set.</p><p>Later in this paper we will define separate rule sets for each of these stages. Rule sets R 1 and R 2 -corresponding to the analysis and synthesis stage respectively -are side-effect free. By matching the left hand side of the rules to a graph, their right hand side can be used to construct another graph. Rules in rule set R 3 - </p><formula xml:id="formula_1">Algorithm 1 DiscoverF SM G(SP G, R 1 , R 2 , R 3 ) 1: Init ← {init/1,</formula><formula xml:id="formula_2">; } 3: RelationGraph ← discover(Init, R 1 , Exclude 1 , SP G) 4: T RelationGraph ← transf orm(Init, R 2 , RelationGraph) 5: F SM G ← discover(init(Init), R 3 , ∅, T RelationGraph) 6: return F SM G</formula><p>corresponding to the transformation stage -are not side-effect free. By matching their left hand side in a graph, their right hand side can be used to modify this same graph.</p><p>The analysis stage and the synthesis stage will make use of the same backtracking algorithm, that tries to pattern match every rule to an environment of the current node, and determines the next neighboring nodes to visit using the matching rules. The transformation stage makes use of a slightly modified backtracking algorithm. This one will try to apply a rule to a node as many times as possible, before moving on the next node. After it visited every node, it will proceed to repeat this procedure with the next rule. The stage ends when the last rule was applied as many times as possible to every node in the graph.</p></div>
<div xmlns="http://www.tei-c.org/ns/1.0"><head n="4">Specification of the transformation rules</head><p>As mentioned earlier, the transformation is realised by two backtracking algorithms, that are performing pattern matching on their respective input graphs with the left hand side (LHS) of certain set of rules, and then apply the right hand side (RHS) of the matching rules to construct an output graph, or -in case of the transformation stage -to modify the input graph. This section describes the algorithms referenced by Figure <ref type="figure">1</ref> and outlines the rule sets utilised by the analysis, transformation and synthesis stages. The keep the discussion concise, we only selected a few rules to present here, and these can only be used to transform small, simple state machines, like the one demonstrated in Section 5. We presented more elaborate rule sets capable of transforming large, complex state machines, in the appendices of <ref type="bibr" target="#b15">[18]</ref>. Our reference implementation is also based on these larger rule sets, and, as described in Section 6, it was successfully tested on state machines, selected from the sources of large, open source, widely used Erlang applications.</p><p>First, we introduce a notation that will be used to denote these rules. The LHS of the rules will consist of edge patterns and logical expressions, featuring relations between nodes of the input graph. In these rules, x always denotes the node that the pattern matching must start on, while other variable names are arbitrary. For example, if a rule has the pattern x def − − → y ∈ SP G E as its LHS, then the rule matches on some x 0 node of the input graph if and only if there is an edge, between the nodes x 0 and some arbitrary y 0 , with the label def. We use a shorthand notation for connecting relations: we write </p><formula xml:id="formula_3">x − → y − → z ⊂ SP G E instead of x − → y ∈ SP G E ∧ y − → z ∈ SP G E .</formula></div>
<div xmlns="http://www.tei-c.org/ns/1.0"><head n="4.1">Analysis stage</head><p>In the analysis stage we traverse part of the semantic program graph of RefactorErl to identify all the nodes used by the following stages, and to attach transformation-specific semantic information to the edges by relabelling them. This traversal is done by the backtracking algorithm described in Figure <ref type="figure">2</ref>, utilising the rules collected in Table <ref type="table">1</ref>.</p><p>The backtracking algorithm in Figure <ref type="figure">2</ref> starts by visiting and expanding the nodes in the Init set. To expand a node x 0 , it iterates over all the rules in Table <ref type="table">1</ref>, and tries to pattern match these rules on x 0 . For any matching rules, it adds the RHS of the matching rule to the node in the output graph, corresponding to x 0 , and puts the Algorithm 2 discover(Init, Rules, Exclude, G)</p><formula xml:id="formula_4">1: V ← Init 2: E ← ∅ 3: V isited ← ∅ 4: S ← stack(Init) 5: while S = ∅ do 6: v ← S.pop() 7: if v ∈ V isited then 8:</formula><p>V isited.add(v) V.add(endpoint(e)) endpoint, denoted in the rules by y, in the stack to expand later. If the type of the edge in the RHS of the matching rule is featured in Exclude, then the y endpoint will not be expanded. As both the input graph and the rule sets are finite, the backtracking algorithm is guaranteed to terminate, and operates in polynomial time.</p><p>Apart from identifying the neighbouring nodes to be visited by the backtracking algorithm, the rules in Table <ref type="table">1</ref> describe how certain edge sequences encountered in the semantic program graph will be labelled in the analysed semantic program graph. These labels indicate the semantic roles of the endpoints of their respective edges, and these roles will determine how each node will be treated in the subsequent stages. Labels ; label is a special label that needs to substituted to other labels as specified by Table <ref type="table" target="#tab_2">2</ref>. This substitution only serves to make our definition more compact: it can be eliminated in design time by adding new rules by combining the conditions of the rules in Table <ref type="table">1</ref> and Table <ref type="table" target="#tab_2">2</ref>. Because of this, the substitution step does not need to appear in the algorithm either. As for the labels appearing in Table <ref type="table" target="#tab_2">2</ref>, c ; denotes a branching expression at its source, a0 ; and a ; denote ordinary functions, e ; points to a tuple that will be mapped to a stop state, and t ; points to a tuple which contains the name of a state in the state machine. The label 0 ; does not convey any specific semantic meaning, it is only used to specify the next nodes to be visited by the backtracking algorithm.</p><p>In later stages, transition functions will be mapped to states, and each function clause will correspond to a state transition leading out of that state, with a trigger label constructed from the first parameter (the event) of the clause. Since the gen fsm specification allows for multiple clauses to have the same event, this mapping could results in non-deterministic state machines. To avoid this, we introduce a choice state for every group of clauses with the same event. This way there will be only one transition for each event between the original state and the choice state, and we will use guard labels on the transitions leading out from the choice states to distinguish between clauses in the same group. Ordinary functions with multiple clauses, similar to branching expressions, will be mapped to choice states, while those with single clauses do not have to be denoted in the resulting state machine.</p><p>In Table <ref type="table" target="#tab_2">2</ref>, the predicate multiclause(x) is true iff the node x is a node in the semantic program graph, representing a function with multiple clauses. Let ∼ denote a relation between function clauses, and let c 1 ∼ c 2 be true for c 1 , c 2 of a function iff their first parameter patterns are identical. As ∼ is an equivalence relation, it partitions the clauses of a function into equivalence classes. In Table <ref type="table">1</ref> the predicate multiclausegroup(x) is true iff the node x represents a transition function with multiple clauses and there is at least one class of ∼ with at least two elements, i.e. the function has at least two clauses with identical first parameter patterns. If x is an atom, f ind(x) denotes the set of all functions with the same name as the value of x.</p><p>Table <ref type="table">1</ref>: Rules for the analysis stage LHS RHS §1  </p><formula xml:id="formula_5">x def − − → y ∈ SP GE ∧ multiclausegroup(y) x s ; y §2 x def − − → y ∈ SP GE ∧ ¬ multiclausegroup(y) x s0 ; y §3 x def − − → y fclause/i − −−−−− → cl pattern/1 − −−−−−− → patt ⊂ SP GE x trigger/i ; patt §4 x [type=atom] ∈ SP GV ∧ y ∈ f ind(x) x nameof ; y §5 x [type=f unc|f un expr] fclause/i − −−−−− → clause cret − −− → y ⊂ SP GE x fsm0/i ; y §6 type(x) ∈ {if expr|case expr|try expr|receive expr} ∧ x (exprcl|catchcl|aftercl)/i − −−−−−−−−−−−−−−−− → cl cret − −− → y ∈ SP GE §7 type(x) ∈ {case expr|try expr|receive expr} ∧ x exprcl/i −−−−−→ cl pattern/1 − −−−−−− → patt ⊂ SP GE x condbranch/i ; patt §8 x [type=case expr|try expr] exprcl − −−− → cl1 ∈ SP GE ∧ x headcl/i − −−−−− → cl2 cret − −− → y ⊂ SP GE x condhead/i ; y §9 x [type=tuple] elem/1 − −−−− → z ∈ SP GE ∧ z flow ; atom [value= next state | ok ] ∈ SP GE ∧ x elem/2 − −−−− → y ∈ SP GE x fsm0 ; y §10 x [type=tuple] elem/1 − −−−− → z ∈ SP GE ∧ z flow ; atom [value= reply ] ∈ SP GE ∧ x elem/3 − −−−− → y ∈ SP GE</formula></div>
<div xmlns="http://www.tei-c.org/ns/1.0"><head n="4.2">Transformation stage</head><p>In the transformation state we reduce the analysed semantic program graph to acquire a graph that can be easily mapped to a state machine. For this stage we slightly modified the backtracking algorithm. This algorithm iterates over all the rules in a predetermined order, and in each iteration it visits the nodes of the analysed semantic program graph to apply the actual rule as many times as possible. Since the matching rules specified in Table <ref type="table" target="#tab_3">3</ref> always eliminate some of the edges from their LHS, the algorithm is guaranteed to terminate. Since eliminated nodes will not be visited again, this algorithm also operates in polynomial time.</p><p>Algorithm 3 transf orm(Init, Rules, G) Require: Rules is ordered according to the transformation rule set 1: for r ∈ Rules do 2:</p><p>V isited ← Init if v ∈ V isited then 7:</p><p>V isited.add(v) </p></div>
<div xmlns="http://www.tei-c.org/ns/1.0"><head>S.add(G.children(v))</head><p>12:</p><p>end if</p></div>
<div xmlns="http://www.tei-c.org/ns/1.0"><head>13:</head><p>end while 14: end for We used a procedural approach to describe the rules for this stage: the RHS of these rules contains simple statements that are inserting or removing edges to or from the input graph. If the LHS of a rule matches, the modifications specified in the RHS are performed on the input graph. As mentioned previously, we only included in this paper those rules that are necessary to demonstrate the transformation of a small example state machine, and a more elaborate extended rule set capable of transforming any Erlang state machines is presented in the appendices of <ref type="bibr" target="#b15">[18]</ref>. While the rules presented here could have been expressed with a declarative approach, it would have been more difficult to express declaratively those in the extended transformation rule set. The rule §11 contracts nameof ; edges, while §12 contracts s0 ; edges. The rule §13 contracts t ; and 0 ; edges in a way that the new edge inherits the edge sequence number of the contracted edge. With the exception of the placeholder 0 ;, all these edges can be used to eliminate unnecessary or unwanted segments from the analysed program graph. For example, branches that would be mapped to a choice state with only one outgoing transitions, or for example dead ends, i.e. paths that would be mapped to transitions without a target state. We also described these eliminations in <ref type="bibr" target="#b15">[18]</ref>. </p></div>
<div xmlns="http://www.tei-c.org/ns/1.0"><head n="4.3">Synthesis stage</head><p>In the last stage we map the reduced analysed semantic program graph to a state machine. The purpose of the previous transformation stage was to make the rules in the synthesis stage simpler. As shown in Figure <ref type="figure">1</ref>, this stage reuses the backtracking algorithm in Figure <ref type="figure">2</ref> with the rules specified in Table <ref type="table" target="#tab_4">4</ref>. This time the algorithm expands states instead of program graph nodes. In the analysis stage, the LHS of the rules were pattern matched to the input semantic program graph, and the news edges identified by the RHS were added to the output analysed program graph. In the synthesis state, the input graph is the reduced analysed program graph and output graph is a state machine, thus the LHS pattern matching is performed on the reduced analysed graph, while the new edges in the RHS are transitions, which are added to the state machine. Similar to the fsm0 ; label of the first stage, the lab − − → labels in the RHS of the rules in Table <ref type="table" target="#tab_4">4</ref> can be substituted according to Table <ref type="table" target="#tab_5">5</ref>. Again, this label substitution is only required to keep the description concise, and it can be accomplished during design time by adding new rules that combine the corresponding conditions and rules of the two tables.  </p><formula xml:id="formula_6">v lab − − → stop(y) §16 node(v) c ; branch v lab − − → choice(branch)</formula></div>
<div xmlns="http://www.tei-c.org/ns/1.0"><head n="5">Demonstration of the state machine transformation</head><p>In this section we demonstrate the transformation method previously introduced, by presenting the intermediate results of the transformation of a small Erlang state machine. Although we intentionally selected a simple state machine for this example, an implementation of the transformation was also successfully tested on large state machines selected from open source Erlang applications. The code of the example state machine shown in Figure <ref type="figure">3</ref> describes the language of identifiers: words starting with letters and proceeding with letters, numbers or underscores. We omitted from the source code some of the callbacks required by the gen fsm specification, and also those functions that can be used to interact with the state machines to initialise the state machine, and to send events to it. In this example events could be letters read from some input word. The state machine accepts identifiers ending with the line ending character ($\n), and rejects every other words. The initial state of this state machine is pos1, where it transitions to a rejecting state upon receiving a non-letter character, and transitions to posOther state upon receiving a letter. In posOther, it transitions to an accepting state upon receiving a line ending character, stays in posOther upon receiving alphanumeric characters or underscores, and transitions to a rejecting state upon receiving any other event.</p><p>1 −module ( i d v a l i d a t o r ) .</p><p>2 −b e h a v i o u r ( g e n f s m ) .   </p></div>
<div xmlns="http://www.tei-c.org/ns/1.0"><head n="5.1">Demonstration of the analysis stage</head><p>The first stage of the transformation applies the algorithm in Figure <ref type="figure">2</ref> to the semantic program graph. The result of this analysis stage is shown in Figure <ref type="figure" target="#fig_8">5</ref>. This stage identifies all the nodes used by the following stages and attaches transformation-specific semantic information to the edges by relabelling them.</p><p>The first node to analyse is the init/1 function node, since init/1 is element of the Init set. This function has only one clause, thus the first rules that match are §2 and §3. At this point the resulting graph consists of the edges ; is a member of Exclude 1 , we will not expand the target node of this edge. The next node to expand, as specified by §2, is the form node. The rule §5 matches, thus we add an fsm0</p><p>; edge to the result graph. We may choose to do the substitution of fsm0</p><p>; right now, based on ; edge to the result. Finally §4 on the atom node, thus we add to results a nameof ; edge, pointing to the semantic node of the pos1/3 function. At this point the analysis of the init/1 function concludes, since we found the name of the first state, and the next function to analyse.</p><p>On the pos1/3 function node we can match §2 and §3 again, since all the clauses of pos1/3 have different events. Now, we can match §5 on two branches, one for each clause. The first tuple represents a stop state, thus we have to substitute are in Exlcude 1 , thus their target nodes -used in later stages to construct guards for the state machine -will not be expanded. In the left branch that matched §6, we substitute  </p></div>
<div xmlns="http://www.tei-c.org/ns/1.0"><head n="5.2">Demonstration of the transformation stage</head><p>In the transformation stage we start with the analysed program graph, resulting from the analysis stage, shown in Figure <ref type="figure" target="#fig_8">5</ref>, and reduce it to graph, that can be mapped to a state machine model relatively easily. The result of the transformation stage is depicted by Figure <ref type="figure" target="#fig_12">6</ref>.</p><p>Since in this example the state machine we transform is small, we only have to use a few reductions. To reduce the analysed semantic program graph of larger state machines may require more kinds of reduction rules, which are described in the appendix of <ref type="bibr" target="#b15">[18]</ref>. The first step is to contract every ; edges. We could use the t ; edges to recognise and eliminate branches that violate the syntactic convention about tuples in function return points, containing the atom with the name of the next state, specified in the gen fsm specification. The example program graph follows the specification, therefore these edges are not needed anymore, and can be contracted, by applying §13. As a result we get the reduced analysed program graph shown in Figure <ref type="figure" target="#fig_12">6</ref>.</p></div>
<div xmlns="http://www.tei-c.org/ns/1.0"><head n="5.3">Demonstration of the synthesis stage</head><p>In this stage we map the reduced analysed program graph, shown in Figure <ref type="figure" target="#fig_12">6</ref>, unto a state machine model, depicted by Figure <ref type="figure" target="#fig_15">7</ref>. First, we add init(init/1) (the initial state created from the function node of init/1) to the state machine, since init/1 is the only element of Init in this example. The rule §14 matches the node corresponding this state (i.e. init/1) with the function node of pos1/3, thus we add state(pos1/3), and a transition to the state machine. We may choose to do the substitution of edges. With the match of §14, we added state(posOther/3) to the state machine. The corresponding posOther/3 node can be analysed similarly to pos1/3. Finally, we get the result of the transformation, a complete state machine, as shown in Figure <ref type="figure" target="#fig_15">7</ref>. To test and measure the previously presented transformation method during actual physical execution, we also created a reference implementation in Erlang. Instead of creating an application that communicates with a RefactorErl instance via some remote communication protocol, we realised the implementation by extending the source code of the open source RefactorErl framework to eliminate the need of creating a bridge, and to minimise the number of dependencies. To implement the matching rules, we were able to make use of the function clause pattern matching in the Erlang language, and used memoisation technique to avoid repetitive evaluation of functions called from multiple places in the source code. We also implemented a few small extension not mentioned in this paper. For example, initialising special states to stand in place of undiscoverable states, or the recognition of a state machine based on the functions calls that start that state machine. We also used Erlang to generate the XMI files storing the resulting UML state machines, and used txtUML <ref type="bibr" target="#b10">[13]</ref>, also developed at the Eötvös Loránd University (ELTE) to generate graphical diagrams from these UML state machine models.</p><p>We executed the implemented algorithm on Erlang state machines found in large, popular, open source Erlang applications. Our sample state machines are from the sources of the Ejabberd communication server <ref type="bibr" target="#b3">[6]</ref>, the Riak distributed NoSQL database <ref type="bibr" target="#b6">[9]</ref>, and the Erlang OTP library <ref type="bibr" target="#b11">[14]</ref>. Unfortunately, the more general state machines are less commonly used than the more specialised behaviours, like gen server, and gen event, which means we had to test on a smaller sample. Still, the selected sample of state machines seems to have a nice enough variety both in length and complexity.</p><p>Our results are summarised in Table <ref type="table" target="#tab_7">6</ref>, containing, for each Erlang state machine module the number of lines of code in the module, the number of discovered states and transitions in the resulting state machine, and the runtime of the transformation (minimum, maximum, average, median runtimes in microseconds). To measure runtime, we repeated every measurement 500 times for each file, thus creating a 500 element sample for each Erlang state machine. The runtime data does not include the time needed to load the respective Erlang applications in the RefactorErl databases, since this operation only has to be performed once for every software application, and in general, the size of the complete application source code is expected to be independent from the size of the individual Erlang state machines the application contains. Since the resulting state machines usually contain choice states, the measured number of states and edges are expected to be higher than the (ordinary) states explicitly defined by the Erlang state machines. Taking our use case into account, fast runtimes are not of critical importance to the success of the transformation. However, even the slowest execution time, measured with tls connection module in Erlang OTP, is quite small with 3 seconds. We have to remind the reader though, that we used memoisation in the implementation to optimise the runtime: without the elimination of repetitive SPG branch evaluations, the algorithm would be noticeably slower.</p><p>According to Figure <ref type="figure" target="#fig_16">8</ref> (after eliminating the outlier tls connection), the number of lines positively correlates with time needed to execute the transformation. This phenomenon can be explained by the fact, that the algorithm needs more time to analyse deeper function return points, and the depth of these return points are likely correlated with the length of the source code of the module. Although not shown here, the same connection can be observed between the states in the resulting state machines and the transformation execution time. Since we mapped branching expressions to choice states, and deeper function return points are more likely to contain such branching expressions, it is also more likely that we will create more choice states for those state machines with deeper return points and longer transformation execution times. Figure <ref type="figure">9</ref> also shows a positive, although less definite correlation between the number of lines and the number of states. Using the same reasoning, we conjecture that deeper function return points will have more lines, and are also more likely to contain branching expressions. Conversely, Erlang state machines with more states, and therefore more transition function definitions, are also more likely to contain more lines of code. Still, because of the low number of state machine modules in the samples, these assertions probably require more thorough research with a bigger sample size, and perhaps with the use of more advanced metrics.</p></div>
<div xmlns="http://www.tei-c.org/ns/1.0"><head n="7">Related work</head><p>While most CASE tools support source code generation from UML models, the inverse operation, generation of UML models from source code (code-model transformation) is less prevalent. This is probably explained by that code-model transformation requires complex static and/or dynamic analysis tools. For the most popular objectoriented languages, industrial tools suitable for this task usually support the discovery of UML class diagrams and sequence diagrams from the program sources. Such tool are for example ObjectAid <ref type="bibr" target="#b5">[8]</ref> and Eclipse MoDisco <ref type="bibr" target="#b2">[5]</ref> for Java, Microsoft Visio [3] and Altova UModel [1] for C# s Visual Basic, Visio and Doxygen <ref type="bibr" target="#b0">[2]</ref> for C++. Another interesting approach makes use of static and dynamic analysis techniques to detect design patterns in object-oriented source code <ref type="bibr" target="#b20">[23]</ref>.</p><p>Model transformations, a recent, but well researched area can also be of interest concerning state machine transformations. While this methodology is mostly used to specify and execute transformations between models, it can be extended to also handle entities not usually considered to be models, such as syntax trees. Closely related to the topic of our current paper, we presented a procedure to map a subgraph of the SPG of RefactorErl to an SPG model by utilising triple graph grammars <ref type="bibr" target="#b19">[22]</ref> to transform this SPG model to a valid UML state machine model <ref type="bibr" target="#b16">[19]</ref>. By employing a formal mathematical theory, this approach provably obtained advantageous properties concerning among others the correctness and completeness of its results and the efficiency of its execution. On the other hand, since it utilises high level model transformation concepts, implementations of that procedure are expected to be a magnitude slower than the directly implementable approach presented in our current paper.</p><p>Similarly to the tool introduced in the present paper, Erlesy <ref type="bibr" target="#b1">[4]</ref> is another tool that can be used to visualise Erlang state machines. Instead of utilising a powerful, but complex static analysis framework, Erlesy uses standard Erlang tools to parse state machine source code. Erlesy does not include choice states and guards in its output, thus the results will possibly represent non-deterministic state machines. Unlike our approach, Erlesy uses loop edges to model the handle callbacks of the gen fsm specification: an advantage of this approach is that it follows gen fsm semantics more closely, a disadvantage is that it inevitably clutters the resulting state machine graphs with loop edges. Erlesy is a readily usable, lightweight solution to visualize Erlang state machines in various output formats, like Graphviz, PlantUML or D3.js.</p><p>There is also a mature methodology for discovering deterministic finite state machines using dynamic code analysis, called state machine induction and behavioural inference. Procedures applying this methodology execute the analysed program based on specific use case scenarios (e.g. a sequence of function calls), and collect information to generate a state machine model. This task requires the elimination of non-deterministic transitions, and transitions featuring recurring execution traces. Such state machine reducing methods are the k-tail algorithm, and the QSM algorithm. QSM offers the user various valid reductions, and proceeds to perform the reductions chosen by the user. Later methods can eliminate the need for these user dialogues by utilising static source code analysis to find good answers automatically and with high precision <ref type="bibr" target="#b24">[27]</ref>. The Erlang language is also well suited for this task due to its statelessness and advanced program execution tracing facilities <ref type="bibr" target="#b7">[10]</ref>.</p><p>While the dynamic approach to state machine discovery enjoys benefits from the well defined methodology, the requirement for use case scenarios hinders its usability for large systems. With static analysis, it is possible to discover the complete state machine, relying only on the source code. One of the difficulties arising from using static analysis is identifying the relation between the implementation level programming patterns and high level state machine concepts. And even if we solve this problem, in some special cases it is still impossible for pure static analysis to filter out components (e.g. states, transitions) that can be never reached during program executing (e.g. because of conditions that can only be evaluated to false). Thus, it can be stated that both the dynamic and static analysis approaches have their advantages and disadvantages, therefore the choice is dependent upon the goals and requirements of the task at hand. Our approach strongly relies on static analysis, since the requirements of the gen fsm behaviour <ref type="bibr" target="#b11">[14]</ref> makes it easier to identify and analyse the programming constructs relevant to state machines, and the RefactorErl framework provides the means to perform deep and comprehensive static analysis on Erlang source code.</p></div><figure xmlns="http://www.tei-c.org/ns/1.0" xml:id="fig_0"><head></head><label></label><figDesc>Edges in the semantic program graph are ordered: we denote restrictions on the sequence number of an edge by denoting the number after the edge label. E.g. a rule with x clause/2 − −−−−− → y ∈ SP G E in its LHS matches on x 0 only if there is an edge with the label clause and the sequence number 2 between x 0 and some other node. Unnumbered edges in the patterns may match edges of the input graph with arbitrary sequence numbers. Nodes in the semantic program graph can also possess various properties: we denote restrictions on a property of a node with an equality expression between braces after the node. E.g. x[type = tuple] elem/1 − −−−− → y ∈ SP G E matches on some node x 0 only if the pattern x elem/1 − −−−− → y ∈ SP G E matches and the type property of x 0 is of the value tuple. Pattern nodes without property restrictions may match nodes with arbitrary values on their properties.</figDesc></figure>
<figure xmlns="http://www.tei-c.org/ns/1.0" xml:id="fig_2"><head></head><label></label><figDesc>at their source, nameof ; connects an atom with a function with the same name as the value of that atom, and the edges with trigger ; and cond ; labels point to nodes that will be used to construct trigger and guard labels in the final state machine. Thefsm0</figDesc></figure>
<figure xmlns="http://www.tei-c.org/ns/1.0" xml:id="fig_3"><head></head><label></label><figDesc>) = if expr|case expr|try expr|receive expr c ; type(y) = f unc|f un expr ∧ ¬ multiclause(y) a0 ; type(y) = f unc|f un expr ∧ multiclause(y) a ; type(y) = atom e ; type(y) = tuple ∧ y elem/1 − −−−− → z ∈ SP G E ∧ z flow ; atom [value= stop ] ∈ SP G E e ; type(y) = tuple ∧ y elem/1 − −−−− → z ∈ SP G E ∧ z flow ; atom [value= next state | reply | ok ] ∈ SP G E t</figDesc></figure>
<figure xmlns="http://www.tei-c.org/ns/1.0" xml:id="fig_6"><head>3 4 %%</head><label>4</label><figDesc>The s t a t e machine t h a t a c c e p t s i d e n t i f i e r s , d e s c r i b e d 5 %% by t h e r e g u l a r e x p r e s s i o n ˆ[A−Za−z ] [A−Za−z0 −9 ] * $ 6 7 [ . . . ] 8 9 i n i t ( ) −&gt; 10 {ok , pos1 , [ ] } . 11 12 pos1 ( $ \n , , ) −&gt; { st op , normal , { [ ] , r e j e c t } , [ ] } ; 13 pos1 (X, , ) −&gt; 14 case a l p h a (X) of 15 true −&gt; { r e p l y , { [X] , s t e p } , posOther , [ ] } ; 16 f a l s e −&gt; { st op , normal , { [X] , r e j e c t } , [ ] } 17 end . 18 19 posOther ( $ \n , , ) −&gt; { st op , normal , { [ ] , a c c e p t } , [ ] } ; 20 posOther (X, , ) −&gt; 21 case ( a l p h a n u m e r i c (X) or X == $ ) of 22 true −&gt; { r e p l y , { [X] , s t e p } , posOther , [ ] } ; 23 f a l s e −&gt; { st op , normal , { [X] , r e j e c t } , [ ] } 24 end . 25 [ . . . ]</figDesc></figure>
<figure xmlns="http://www.tei-c.org/ns/1.0" xml:id="fig_7"><head>Figure 3 :Figure 4 :</head><label>34</label><figDesc>Figure 3: The state machine that recognizes the language of identifiers</figDesc></figure>
<figure xmlns="http://www.tei-c.org/ns/1.0" xml:id="fig_8"><head>Figure 5 :</head><label>5</label><figDesc>Figure 5: Analysed semantic program graph, resulting from the analysis stage</figDesc><graphic coords="15,125.55,155.85,364.51,427.86" type="bitmap" /></figure>
<figure xmlns="http://www.tei-c.org/ns/1.0" xml:id="fig_9"><head>;</head><label></label><figDesc>, and their nodes. Since trigger/1</figDesc></figure>
<figure xmlns="http://www.tei-c.org/ns/1.0" xml:id="fig_10"><head></head><label></label><figDesc>There are no rules matching on this branch, thus the algorithm backtracks to the other branch. In the other branch fsm0 ; is substituted to c ;. We can match §6, §7, and §8 on the case expr node and its clauses. Again, cond head ; , and cond branch ;</figDesc></figure>
<figure xmlns="http://www.tei-c.org/ns/1.0" xml:id="fig_11"><head></head><label></label><figDesc>then continue the analysis of this branch by matching §10 on the tuple, and swap fsm0 ; with e ;. Finally, we find the posOther/3 function node by matching §4. The analysis of posOther/3 is almost identical, except that the last matching of §4 will result in a nameof ; edge pointing back to the posOther/3 itself. With this the analysis stage concludes.</figDesc></figure>
<figure xmlns="http://www.tei-c.org/ns/1.0" xml:id="fig_12"><head>Figure 6 :</head><label>6</label><figDesc>Figure 6: Reduced analysed semantic program graph, resulting from the transformation stage</figDesc><graphic coords="16,174.15,273.81,267.30,250.84" type="bitmap" /></figure>
<figure xmlns="http://www.tei-c.org/ns/1.0" xml:id="fig_13"><head></head><label></label><figDesc>applying §11. Next we contract the s0 ; edges by applying §12. While the s ; edges highlight transition functions with multiple clauses, each having the same event parameter, this small program did not have these kinds of functions, therefore the analysed program graph features only s0</figDesc></figure>
<figure xmlns="http://www.tei-c.org/ns/1.0" xml:id="fig_14"><head>2 ; 2 ;</head><label>22</label><figDesc>lab − − → right now based on Table 5, swapping it to trigger label constructed from the joker pattern pointed by the trigger/1 ; edge. Next, we can match both §15 and §16 on the pos1/3 node. The former results in adding a stop state to the state machine, while the latter results in adding a choice state. To substitute lab − − → for a trigger, as specified by the substitution rule, we have utilise the edge numbering to select the pattern nodes corresponding to each transitions: the pattern pointed by trigger/1 ; will be used to label the transition of the stop state corresponding to the tuple node pointed by for the choice state corresponding to the branching expression pointed by e/. Next, §14 and §15 matches on the node of the choice state. This time, lab − − → is substituted to a guard, constructed with the appropriate expressions pointed by the cond head ; and cond branch ;</figDesc></figure>
<figure xmlns="http://www.tei-c.org/ns/1.0" xml:id="fig_15"><head>Figure 7 :</head><label>7</label><figDesc>Figure 7: The state machine resulting from the synthesis stage</figDesc><graphic coords="17,198.45,326.33,218.70,218.70" type="bitmap" /></figure>
<figure xmlns="http://www.tei-c.org/ns/1.0" xml:id="fig_16"><head>Figure 8 :</head><label>8</label><figDesc>Figure 8: Algorithm execution times in terms of LoC</figDesc><graphic coords="19,64.80,54.06,233.28,233.28" type="bitmap" /></figure>
<figure xmlns="http://www.tei-c.org/ns/1.0"><head></head><label></label><figDesc></figDesc><graphic coords="3,64.80,54.07,486.00,368.48" type="bitmap" /></figure>
<figure xmlns="http://www.tei-c.org/ns/1.0"><head></head><label></label><figDesc></figDesc><graphic coords="4,137.70,54.07,340.20,212.40" type="bitmap" /></figure>
<figure xmlns="http://www.tei-c.org/ns/1.0" type="table" xml:id="tab_0"><head></head><label></label><figDesc>handle event/3, handle inf o/3, handle sync event/4, code change/4}</figDesc><table /><note>2: Exclude 1 ← { trigger ; , cond * ; , fsmguard</note></figure>
<figure xmlns="http://www.tei-c.org/ns/1.0" type="table" xml:id="tab_2"><head>Table 2 :</head><label>2</label><figDesc>Substitution rules for x</figDesc><table /></figure>
<figure xmlns="http://www.tei-c.org/ns/1.0" type="table" xml:id="tab_3"><head>Table 3 :</head><label>3</label><figDesc>Rules for the transformation stage</figDesc><table><row><cell>LHS</cell><cell></cell><cell></cell><cell></cell><cell></cell><cell></cell><cell>RHS</cell></row><row><cell></cell><cell cols="6">∃i 1 , ..., i n (n ≥ 1) :</cell></row><row><cell></cell><cell cols="2">x</cell><cell cols="3">e/i1 ; y i1</cell><cell>nameof ; z ∧ . . .</cell><cell>∀k ∈ {i 1 , ..., i n } (insert(x ∀k ∈ {i 1 , ..., i n } (</cell><cell>e/k ; z)) ;</cell></row><row><cell></cell><cell>x</cell><cell></cell><cell cols="3">e/in ; y in</cell><cell>nameof ; z ∧</cell><cell>remove(x</cell><cell>e/k ; y k</cell><cell>nameof ; z)</cell></row><row><cell cols="4">j : j ∈ {i 1 , ..., i n } ∧ x</cell><cell cols="2">e/j ; y j</cell><cell>nameof ; z</cell><cell>)</cell></row><row><cell>§11</cell><cell></cell><cell></cell><cell></cell><cell></cell><cell></cell></row><row><cell></cell><cell cols="6">∃i 1 , ..., i n (n ≥ 1) :</cell></row><row><cell></cell><cell cols="6">S ∈ {t, 0, a, c, e, s} ∧</cell></row><row><cell></cell><cell></cell><cell></cell><cell>x x</cell><cell>s0 ; y s0 ; y</cell><cell cols="2">S/i1 ; z i1 ∧ . . . S/in ; z in ∧</cell><cell>∀k ∈ {i 1 , ..., i n } ( insert(x S/k ; z k ) ; remove(y S/k ; z k ) ) ;</cell></row><row><cell></cell><cell></cell><cell></cell><cell></cell><cell></cell><cell></cell><cell>S/j ; z j</cell><cell>remove(x</cell><cell>s0 ; y)</cell></row><row><cell>§12</cell><cell></cell><cell></cell><cell></cell><cell></cell><cell></cell></row><row><cell></cell><cell cols="4">R ∈ {t, 0} ∧</cell><cell></cell></row><row><cell cols="5">S ∈ {a, c, e, s} ∧</cell><cell></cell><cell>insert(x</cell><cell>S/i ; z) ;</cell></row><row><cell>x</cell><cell>R/i ; y</cell><cell cols="3">S ; z</cell><cell></cell><cell>remove(x</cell><cell>R/i ; y</cell></row><row><cell>§13</cell><cell></cell><cell></cell><cell></cell><cell></cell><cell></cell></row></table><note>j : j ∈ {i 1 , ..., i n } ∧ x s0 ; y S ; z)</note></figure>
<figure xmlns="http://www.tei-c.org/ns/1.0" type="table" xml:id="tab_4"><head>Table 4 :</head><label>4</label><figDesc>Rules for the synthesis stage</figDesc><table><row><cell>LHS</cell><cell>RHS</cell></row><row><cell>node(v)</cell><cell></cell></row><row><cell>§14</cell><cell></cell></row></table><note>e ; y [type =tuple] v lab − − → state(y) §15 node(v) e ; y [type=tuple]</note></figure>
<figure xmlns="http://www.tei-c.org/ns/1.0" type="table" xml:id="tab_5"><head>Table 5 :</head><label>5</label><figDesc>Substitution rules for v</figDesc><table><row><cell>lab − − → u</cell></row></table></figure>
<figure xmlns="http://www.tei-c.org/ns/1.0" type="table" xml:id="tab_6"><head>Table 2 ,</head><label>2</label><figDesc>swapping it to The left hand side of §9 matches the tuple node, thus after substituting</figDesc><table /><note>t ;. fsm0 ; , we add an e</note></figure>
<figure xmlns="http://www.tei-c.org/ns/1.0" type="table" xml:id="tab_7"><head>Table 6 :</head><label>6</label><figDesc>Runtime test results of the implemented algorithm</figDesc><table><row><cell>File name</cell><cell cols="7">Lines of code States Transitions Min (µs) Max (µs) Avg (µs) Med (µs)</cell></row><row><cell></cell><cell></cell><cell></cell><cell>Ejabberd</cell><cell></cell><cell></cell><cell></cell><cell></cell></row><row><cell>ejabberd c2s</cell><cell>3128</cell><cell>50</cell><cell>79</cell><cell>321354</cell><cell>519876</cell><cell>339679</cell><cell>343389</cell></row><row><cell>ejabberd http bind</cell><cell>1236</cell><cell>28</cell><cell>44</cell><cell>137083</cell><cell>170189</cell><cell>144412</cell><cell>144956</cell></row><row><cell>ejabberd http ws</cell><cell>355</cell><cell>22</cell><cell>25</cell><cell>52735</cell><cell>72020</cell><cell>58953</cell><cell>58706</cell></row><row><cell>ejabberd odbc</cell><cell>692</cell><cell>17</cell><cell>27</cell><cell>46294</cell><cell>64307</cell><cell>50179</cell><cell>51069</cell></row><row><cell>ejabberd s2s in</cell><cell>712</cell><cell>38</cell><cell>54</cell><cell>91495</cell><cell>126085</cell><cell>99134</cell><cell>99422</cell></row><row><cell>ejabberd s2s out</cell><cell>1367</cell><cell>84</cell><cell>113</cell><cell>201523</cell><cell>242354</cell><cell>209178</cell><cell>210240</cell></row><row><cell>ejabberd service</cell><cell>404</cell><cell>26</cell><cell>30</cell><cell>51757</cell><cell>91737</cell><cell>58527</cell><cell>58115</cell></row><row><cell>eldap</cell><cell>1196</cell><cell>23</cell><cell>39</cell><cell>106526</cell><cell>123567</cell><cell>113383</cell><cell>113893</cell></row><row><cell>mod irc connection</cell><cell>1581</cell><cell>30</cell><cell>41</cell><cell>108223</cell><cell>150603</cell><cell>116199</cell><cell>116257</cell></row><row><cell>mod muc room</cell><cell>4501</cell><cell>35</cell><cell>81</cell><cell>164997</cell><cell>280537</cell><cell>172017</cell><cell>173004</cell></row><row><cell>mod proxy65 stream</cell><cell>291</cell><cell>33</cell><cell>37</cell><cell>51259</cell><cell>69289</cell><cell>58666</cell><cell>58485</cell></row><row><cell>mod sip proxy</cell><cell>458</cell><cell>23</cell><cell>28</cell><cell>40422</cell><cell>61556</cell><cell>44489</cell><cell>45057</cell></row><row><cell></cell><cell></cell><cell></cell><cell>Riak</cell><cell></cell><cell></cell><cell></cell><cell></cell></row><row><cell>riak kv 2i aae</cell><cell>695</cell><cell>19</cell><cell>31</cell><cell>77877</cell><cell>193215</cell><cell>80248</cell><cell>83386</cell></row><row><cell>riak kv get fsm</cell><cell>787</cell><cell>20</cell><cell>17</cell><cell>31662</cell><cell>58225</cell><cell>33244</cell><cell>35118</cell></row><row><cell>riak kv put fsm</cell><cell>1055</cell><cell>29</cell><cell>40</cell><cell>81231</cell><cell>148422</cell><cell>83690</cell><cell>87103</cell></row><row><cell>riak kv mrc sink</cell><cell>439</cell><cell>25</cell><cell>41</cell><cell>79229</cell><cell>147276</cell><cell>81694</cell><cell>85265</cell></row><row><cell></cell><cell></cell><cell></cell><cell>Erlang OTP</cell><cell></cell><cell></cell><cell></cell><cell></cell></row><row><cell>ssh connection handler</cell><cell>1721</cell><cell>56</cell><cell>131</cell><cell>3941</cell><cell>19818</cell><cell>4222</cell><cell>5200</cell></row><row><cell>tls connection</cell><cell>975</cell><cell>72</cell><cell>103</cell><cell>3197221</cell><cell>3438752</cell><cell>3290901</cell><cell>3292256</cell></row></table></figure>
		</body>
		<back>

			<div type="acknowledgement">
<div xmlns="http://www.tei-c.org/ns/1.0"><head n="8">Conclusions</head><p>In this paper, we introduced a method to transform Erlang state machines, implementing the gen fsm behaviour, to state machines described by UML, or similar state machine languages. To analyse Erlang programs, we used the RefactorErl static analysis framework. We also defined an UML-compatible state machine representation to denote the target state machines of the transformations. The presented method consists of three stages: an analysis stage, a transformation stage, and a synthesis stage. In each stage, a backtracking algorithm is executed on the output of the last stage (or, in the case of the first stage, the RefactorErl Semantic Program Graph), and each stage utilises a separate set of transformation rules by means of pattern matching. The algorithms themself are general enough not to depend on any static analysis framework, only the presented transformation rules depend on the structural details of the RefactorErl Semantic Program Graph. By separating the algorithm and the rules, we made it more easier to the extend of the transformation: one just has to add more rules to the rule sets. By specifying the bulk of the transformation logic by rules, we also made it possible to parallelise the algorithm to optimise it for environments with multiple processing units. We demonstrated the execution and the results of each stage by a small example. We were able to realise a relatively fast implementation of the algorithm. After testing our implementation on state machines selected from the source code of large, popular, open source Erlang applications, we concluded that the time needed to perform the transformation on an Erlang state machine is positively correlated with the number of lines of code in the program code of the state machine. We also found similar correlation between the transformation execution time and the states created by the transformation. We explained both phenomenon by conjecturing that deeper return point expressions need more time to be analysed, probably have more lines of code, and contain more branching expressions.</p><p>The evaluation of our implementation evidences that the method presented in this paper can be used to construct UML state machine models, even from large and complex Erlang state machines. Still, several opportunity remains for improvement, for example by extending the analysis with more elaborate RefactorErl queries to discover even more state machine elements, or by targeting an even larger subset of all the features provided by the UML state machine language, or even by preparing the method to generate executable state machines.</p></div>
			</div>

			<div type="references">

				<listBibl>

<biblStruct xml:id="b0">
	<monogr>
		<ptr target="http://www.stack.nl/~dimitri/doxygen/.Ac-cessed:2016-06-30" />
		<title level="m">Doxygen -Generate documentation from source code</title>
				<imprint/>
	</monogr>
</biblStruct>

<biblStruct xml:id="b1">
	<monogr>
		<ptr target="https://github.com/haljin/erlesy" />
		<title level="m">Visualising Erlang development</title>
				<imprint>
			<date type="published" when="2016-06-30">2016-06-30</date>
		</imprint>
	</monogr>
</biblStruct>

<biblStruct xml:id="b2">
	<monogr>
		<ptr target="http://www.eclipse.org/MoDisco/" />
		<title level="m">Eclipse MoDisco</title>
				<imprint>
			<date type="published" when="2016-06-30">2016-06-30</date>
		</imprint>
	</monogr>
</biblStruct>

<biblStruct xml:id="b3">
	<monogr>
		<ptr target="https://www.ejabberd.im/" />
		<title level="m">Ejabberd, robust scalable and extensibe XMPP Server</title>
				<imprint>
			<date type="published" when="2016-06-30">2016-06-30</date>
		</imprint>
	</monogr>
</biblStruct>

<biblStruct xml:id="b4">
	<monogr>
		<ptr target="www.omg.org/spec/UML/" />
		<title level="m">OMG Unified Modeling Language Superstructure</title>
				<imprint>
			<date type="published" when="2016-06-30">2016-06-30</date>
		</imprint>
		<respStmt>
			<orgName>Object Management Group</orgName>
		</respStmt>
	</monogr>
</biblStruct>

<biblStruct xml:id="b5">
	<monogr>
		<ptr target="http://www.objectaid.com/home" />
		<title level="m">ObjectAid</title>
				<imprint>
			<date type="published" when="2016-06-30">2016-06-30</date>
		</imprint>
	</monogr>
</biblStruct>

<biblStruct xml:id="b6">
	<monogr>
		<title level="m" type="main">distributed NoSQL database</title>
		<author>
			<persName><forename type="first">K</forename><forename type="middle">V</forename><surname>Riak</surname></persName>
		</author>
		<ptr target="http://basho.com/products/riak-kv/" />
		<imprint>
			<date type="published" when="2016-06-30">2016-06-30</date>
		</imprint>
	</monogr>
</biblStruct>

<biblStruct xml:id="b7">
	<monogr>
		<author>
			<persName><forename type="first">Thomas</forename><surname>Arts</surname></persName>
		</author>
		<author>
			<persName><forename type="first">Cecilia</forename><surname>Holmqvist</surname></persName>
		</author>
		<title level="m">10th International Erlang User Conference</title>
				<meeting><address><addrLine>EUC</addrLine></address></meeting>
		<imprint>
			<date type="published" when="2004">2004</date>
			<biblScope unit="page">10</biblScope>
		</imprint>
	</monogr>
	<note>reverse engineering Erlang software</note>
</biblStruct>

<biblStruct xml:id="b8">
	<analytic>
		<title level="a" type="main">RefactorErl, Source Code Analysis and Refactoring in Erlang</title>
		<author>
			<persName><forename type="first">István</forename><surname>Bozó</surname></persName>
		</author>
		<author>
			<persName><forename type="first">Dániel</forename><surname>Horpácsi</surname></persName>
		</author>
		<author>
			<persName><forename type="first">Zoltán</forename><surname>Horváth</surname></persName>
		</author>
		<author>
			<persName><forename type="first">Róbert</forename><surname>Kitlei</surname></persName>
		</author>
		<author>
			<persName><forename type="first">Judit</forename><surname>Kőszegi</surname></persName>
		</author>
		<author>
			<persName><forename type="first">Máté</forename><surname>Tejfel</surname></persName>
		</author>
		<author>
			<persName><forename type="first">Melinda</forename><surname>Tóth</surname></persName>
		</author>
	</analytic>
	<monogr>
		<title level="m">Proceeding of the 12th Symposium on Programming Languages and Software Tools</title>
				<meeting>eeding of the 12th Symposium on Programming Languages and Software Tools<address><addrLine>Tallin, Estonia</addrLine></address></meeting>
		<imprint>
			<date type="published" when="2011">2011</date>
		</imprint>
	</monogr>
</biblStruct>

<biblStruct xml:id="b9">
	<monogr>
		<title level="m" type="main">Erlang Programming</title>
		<author>
			<persName><forename type="first">Francesco</forename><surname>Cesarini</surname></persName>
		</author>
		<author>
			<persName><forename type="first">Simon</forename><surname>Thompson</surname></persName>
		</author>
		<imprint>
			<date type="published" when="2009">2009</date>
			<publisher>O&apos;Reilly Media</publisher>
		</imprint>
	</monogr>
</biblStruct>

<biblStruct xml:id="b10">
	<analytic>
		<title level="a" type="main">Textual, executable, translatable UML</title>
		<author>
			<persName><forename type="first">Gergely</forename><surname>Dévai</surname></persName>
		</author>
		<author>
			<persName><forename type="first">Gábor</forename><surname>Ferenc Kovács</surname></persName>
		</author>
		<author>
			<persName><forename type="first">Ádám</forename><surname>Ancsin</surname></persName>
		</author>
	</analytic>
	<monogr>
		<title level="m">Proceedings of 14th International Workshop on OCL and Textual Modeling co-located with 17th International Conference on Model Driven Engineering Languages and Systems (MODELS 2014)</title>
				<meeting>14th International Workshop on OCL and Textual Modeling co-located with 17th International Conference on Model Driven Engineering Languages and Systems (MODELS 2014)<address><addrLine>Valencia, Spain</addrLine></address></meeting>
		<imprint>
			<date type="published" when="2014-09-30">September 30. 2014</date>
			<biblScope unit="page" from="3" to="12" />
		</imprint>
	</monogr>
</biblStruct>

<biblStruct xml:id="b11">
	<monogr>
		<title level="m" type="main">Erlang Reference Manual</title>
		<author>
			<persName><forename type="first">A</forename><forename type="middle">B</forename><surname>Ericsson</surname></persName>
		</author>
		<ptr target="http://www.erlang.org/doc/reference_manual/part_frame.html" />
		<imprint/>
	</monogr>
</biblStruct>

<biblStruct xml:id="b12">
	<analytic>
		<title level="a" type="main">Static analysis of function calls in erlang</title>
		<author>
			<persName><forename type="first">Dániel</forename><surname>Horpácsi</surname></persName>
		</author>
		<author>
			<persName><forename type="first">Judit</forename><surname>Kőszegi</surname></persName>
		</author>
	</analytic>
	<monogr>
		<title level="j">e-Informatica Software Engineering Journal</title>
		<imprint>
			<biblScope unit="volume">7</biblScope>
			<biblScope unit="page" from="65" to="76" />
			<date type="published" when="2013">2013</date>
		</imprint>
	</monogr>
</biblStruct>

<biblStruct xml:id="b13">
	<analytic>
		<title level="a" type="main">Modeling semantic knowledge in Erlang for refactoring</title>
		<author>
			<persName><forename type="first">Zoltán</forename><surname>Horváth</surname></persName>
		</author>
		<author>
			<persName><forename type="first">Lászó</forename><surname>Lövei</surname></persName>
		</author>
		<author>
			<persName><forename type="first">Tamás</forename><surname>Kozsik</surname></persName>
		</author>
		<author>
			<persName><forename type="first">Róbert</forename><surname>Kitlei</surname></persName>
		</author>
		<author>
			<persName><forename type="first">Nagyné</forename><surname>Anikó</surname></persName>
		</author>
		<author>
			<persName><forename type="first">Tamás</forename><surname>Víg</surname></persName>
		</author>
		<author>
			<persName><forename type="first">Melinda</forename><surname>Nagy</surname></persName>
		</author>
		<author>
			<persName><forename type="first">Roland</forename><surname>Tóth</surname></persName>
		</author>
		<author>
			<persName><surname>Király</surname></persName>
		</author>
	</analytic>
	<monogr>
		<title level="m">Proceedings of the International Conference on Knowledge Engineering, Principles and Techniques</title>
		<title level="s">Issue of Studia Universitatis Babe-Bolyai, Series Informatica</title>
		<meeting>the International Conference on Knowledge Engineering, Principles and Techniques<address><addrLine>KEPT; Cluj-Napoca, Romania</addrLine></address></meeting>
		<imprint>
			<date type="published" when="2009-07">2009. 2009. Jul 2009</date>
			<biblScope unit="volume">54</biblScope>
			<biblScope unit="page" from="7" to="16" />
		</imprint>
	</monogr>
	<note>Knowledge Engineering: Principles and Techniques</note>
</biblStruct>

<biblStruct xml:id="b14">
	<monogr>
		<title level="m" type="main">Erlang and OTP in Action</title>
		<author>
			<persName><forename type="first">Martin</forename><surname>Logan</surname></persName>
		</author>
		<author>
			<persName><forename type="first">Eric</forename><surname>Merritt</surname></persName>
		</author>
		<author>
			<persName><forename type="first">Richard</forename><surname>Carlsson</surname></persName>
		</author>
		<imprint>
			<date type="published" when="2010">2010</date>
			<publisher>Manning Publications Co</publisher>
			<pubPlace>Greenwich, CT, USA</pubPlace>
		</imprint>
	</monogr>
	<note>1st edition</note>
</biblStruct>

<biblStruct xml:id="b15">
	<analytic>
		<title level="a" type="main">Erlang állapotgépek elemzése és transzformálása UML-re</title>
		<author>
			<persName><forename type="first">Dániel</forename><surname>Lukács</surname></persName>
		</author>
	</analytic>
	<monogr>
		<title level="m">Scientific Students&apos; Associations Conference</title>
				<meeting><address><addrLine>Budapest, Hungary</addrLine></address></meeting>
		<imprint>
			<date type="published" when="2016">2016</date>
		</imprint>
		<respStmt>
			<orgName>ELTE</orgName>
		</respStmt>
	</monogr>
</biblStruct>

<biblStruct xml:id="b16">
	<analytic>
		<title level="a" type="main">Erlang állapotgépek modell alapú és transzformációja UML-re</title>
		<author>
			<persName><forename type="first">Dániel</forename><surname>Lukács</surname></persName>
		</author>
	</analytic>
	<monogr>
		<title level="m">Scientific Students&apos; Associations Conference</title>
				<meeting><address><addrLine>Budapest, Hungary</addrLine></address></meeting>
		<imprint>
			<date type="published" when="2016">2016</date>
		</imprint>
		<respStmt>
			<orgName>ELTE</orgName>
		</respStmt>
	</monogr>
</biblStruct>

<biblStruct xml:id="b17">
	<monogr>
		<title level="m" type="main">Model Driven Architecture with Executable UML(TM)</title>
		<author>
			<persName><forename type="first">Chris</forename><surname>Raistrick</surname></persName>
		</author>
		<author>
			<persName><forename type="first">Paul</forename><surname>Francis</surname></persName>
		</author>
		<author>
			<persName><forename type="first">John</forename><surname>Wright</surname></persName>
		</author>
		<imprint>
			<date type="published" when="2004">2004</date>
			<publisher>Cambridge University Press</publisher>
			<pubPlace>New York, NY, USA</pubPlace>
		</imprint>
	</monogr>
</biblStruct>

<biblStruct xml:id="b18">
	<monogr>
		<title level="m" type="main">Practical UML Statecharts in C/C++: Event-Driven Programming for Embedded Systems</title>
		<author>
			<persName><forename type="first">Miro</forename><surname>Samek</surname></persName>
		</author>
		<imprint>
			<date type="published" when="2009">2009</date>
			<publisher>Electronics &amp; Electrical. Taylor &amp; Francis</publisher>
		</imprint>
	</monogr>
</biblStruct>

<biblStruct xml:id="b19">
	<monogr>
		<title level="m" type="main">Specification of graph translators with triple graph grammars</title>
		<author>
			<persName><forename type="first">Andy</forename><surname>Schürr</surname></persName>
		</author>
		<imprint>
			<date type="published" when="1995">1995</date>
			<publisher>Springer</publisher>
			<biblScope unit="page" from="151" to="163" />
			<pubPlace>Berlin Heidelberg; Berlin, Heidelberg</pubPlace>
		</imprint>
	</monogr>
</biblStruct>

<biblStruct xml:id="b20">
	<analytic>
		<title level="a" type="main">Reverse Engineering of Design Patterns from Java Source Code</title>
		<author>
			<persName><forename type="first">Nija</forename><surname>Shi</surname></persName>
		</author>
		<author>
			<persName><forename type="first">Ronald</forename><forename type="middle">A</forename><surname>Olsson</surname></persName>
		</author>
	</analytic>
	<monogr>
		<title level="m">21st IEEE/ACM International Conference on Automated Software Engineering (ASE&apos;06)</title>
				<imprint>
			<date type="published" when="2006-09">Sept 2006</date>
			<biblScope unit="page" from="123" to="134" />
		</imprint>
	</monogr>
</biblStruct>

<biblStruct xml:id="b21">
	<analytic>
		<title level="a" type="main">Static Analysis of Complex Software Systems Implemented in Erlang</title>
		<author>
			<persName><forename type="first">Melinda</forename><surname>Tóth</surname></persName>
		</author>
		<author>
			<persName><forename type="first">István</forename><surname>Bozó</surname></persName>
		</author>
	</analytic>
	<monogr>
		<title level="m">Central European Functional Programming School</title>
		<title level="s">Lecture Notes in Computer Science</title>
		<imprint>
			<publisher>Springer</publisher>
			<date type="published" when="2012">2012</date>
			<biblScope unit="volume">7241</biblScope>
			<biblScope unit="page" from="440" to="498" />
		</imprint>
	</monogr>
</biblStruct>

<biblStruct xml:id="b22">
	<analytic>
		<title level="a" type="main">First order flow analysis for Erlang</title>
		<author>
			<persName><forename type="first">Melinda</forename><surname>Tóth</surname></persName>
		</author>
		<author>
			<persName><forename type="first">István</forename><surname>Bozó</surname></persName>
		</author>
		<author>
			<persName><forename type="first">Zoltán</forename><surname>Horváth</surname></persName>
		</author>
		<author>
			<persName><forename type="first">Máté</forename><surname>Tejfel</surname></persName>
		</author>
	</analytic>
	<monogr>
		<title level="m">Proceedings of the 8th Joint Conference on Mathematics and Computer Science (MACS)</title>
				<meeting>the 8th Joint Conference on Mathematics and Computer Science (MACS)</meeting>
		<imprint>
			<publisher>ISBN</publisher>
			<date type="published" when="2010">2010</date>
			<biblScope unit="page" from="978" to="963" />
		</imprint>
	</monogr>
</biblStruct>

<biblStruct xml:id="b23">
	<analytic>
		<title level="a" type="main">Static Analysis Based Support for Program Comprehension in Erlang</title>
		<author>
			<persName><forename type="first">Melinda</forename><surname>Tóth</surname></persName>
		</author>
		<author>
			<persName><forename type="first">István</forename><surname>Bozó</surname></persName>
		</author>
		<author>
			<persName><forename type="first">Judit</forename><surname>Kőszegi</surname></persName>
		</author>
		<author>
			<persName><forename type="first">Zoltán</forename><surname>Horváth</surname></persName>
		</author>
		<idno>ISSN 1338-3957</idno>
	</analytic>
	<monogr>
		<title level="j">Acta Electrotechnica et Informatica</title>
		<idno type="ISSN">1335-8243</idno>
		<imprint>
			<biblScope unit="volume">11</biblScope>
			<biblScope unit="issue">03</biblScope>
			<biblScope unit="page" from="3" to="10" />
			<date type="published" when="2011-10">October 2011</date>
			<publisher>Versita</publisher>
		</imprint>
	</monogr>
	<note>print)</note>
</biblStruct>

<biblStruct xml:id="b24">
	<analytic>
		<title level="a" type="main">Reverse Engineering State Machines by Interactive Grammar Inference</title>
		<author>
			<persName><forename type="first">Niel</forename><surname>Walkinshaw</surname></persName>
		</author>
		<author>
			<persName><forename type="first">Kirill</forename><surname>Bogdanov</surname></persName>
		</author>
		<author>
			<persName><forename type="first">Mike</forename><surname>Holcombe</surname></persName>
		</author>
		<author>
			<persName><forename type="first">Sarah</forename><surname>Salahuddin</surname></persName>
		</author>
	</analytic>
	<monogr>
		<title level="m">14th Working Conference on Reverse Engineering (WCRE 2007)</title>
				<imprint>
			<date type="published" when="2007-10">Oct 2007</date>
			<biblScope unit="page" from="209" to="218" />
		</imprint>
	</monogr>
</biblStruct>

				</listBibl>
			</div>
		</back>
	</text>
</TEI>
