EURASIP Journal on Embedded Systems
Volume 2008 (2008), Article ID 310147, 18 pages
doi:10.1155/2008/310147
Research Article

Formal Analysis Tools for the Synchronous Aspect Language Larissa

David Stauch

Verimag, Centre Équation 2, Avenue de Vignate, 38610 Gières, France

Received 17 September 2007; Accepted 18 April 2008

Academic Editor: Michael Mendler

Copyright © 2008 David Stauch. This is an open access article distributed under the Creative Commons Attribution License, which permits unrestricted use, distribution, and reproduction in any medium, provided the original work is properly cited.

Abstract

We present two tools for the formal analysis of the aspect language Larissa, which extends the simple synchronous language Argos. The first tool concerns the combination of design-by-contract with Larissa aspects, and shows how we can apply an aspect not only to a program, but to a specification of programs in form of a contract, and obtain a new contract. The second concerns aspect interferences, that is, aspects that influence each other in an unintended way if they are applied to the same program. We present a way to weave aspects in a less conflict-prone manner, and a means to detect remaining conflicts statically. These tools are quite powerful, compared to those available for other aspect languages.

1. Introduction

Aspect-oriented programming (AOP) offers programming constructs to a base language, which aim at encapsulating crosscutting concerns. These are concerns that cannot be properly captured into a module by the decomposition offered by the base language. AOP languages express crosscutting concerns in aspects, and weave (i.e., compile) them in the base program with an aspect weaver. All the aspect extensions of existing languages (like AspectJ [1]) share two notions: pointcuts and advice. A pointcut describes, with a general property, the program points (called join points), where the aspect should intervene (e.g., all methods of the class , or all methods whose names begin with ). The advice specifies what has to be done at each join point (e.g., execute a piece of code before the normal code of the method).

Reactive systems are control systems that are in constant interaction with their environment. They are often programmed in dedicated languages, which must fulfill specific requirements. First, reactive systems often fulfill safety-critical functions, and thus require the use of formal methods in their development. Programming languages for them must thus be formally defined, and have a connection to verification tools. Furthermore, they usually fulfill several tasks in parallel, and programming languages must thus offer an explicit parallel composition of components.

The family of synchronous languages are such dedicated languages, which are very successfully used to program safety-critical reactive systems, for example, control systems in airplanes or nuclear power stations. Synchronous languages are all based on the same semantic principle, the synchrony hypothesis, which divides time into instants and assumes that reactions of parallel components are atomic, that is, that outputs are emitted as soon as the inputs are received. A second principle is the synchronous broadcast, which allows outputs of a component to be read by other components in parallel. These principles allow to develop synchronous languages that are very expressive and have a clear and simple semantics with strong semantic properties. The family of synchronous languages contains languages with different styles, for example, the dataflow language Lustre [2] and the imperative language Esterel [3]. The simplest language of the family is Argos [4], a hierarchical automata language, based on Mealy machines, which can be composed by different operators.

There are also crosscutting concerns in synchronous programs, which cannot be encapsulated with the parallel composition and other operators of synchronous languages. They are, however, different from crosscutting concerns in programs written in general-purpose languages because they crosscut the parallel structure of reactive programs. Therefore, and because they are usually not formally defined, existing aspect languages cannot be applied to reactive systems. Thus we developed an aspect-oriented extension for Argos, called Larissa [5].

When designing Larissa, we took great care to give it a clean and simple semantics and strong semantic properties, as they are common in synchronous languages. Thus pointcuts are specified as synchronous observers [6], that is, Argos programs that, via the synchronous broadcast, observe the inputs and the outputs of the base program, and compute a safety property on them. This is a semantic and at the same time very expressive mechanism. Larissa has different kinds of advice, and all are specified depending only on the interface of the base program, but not on its implementation. Due to this semantic definition, Larissa aspects preserve the equivalence of base programs.

Having a clean and simple semantics has the advantage of making programs easier to understand for programmers. Furthermore, it allows the semantic analysis of programs. In this paper, we present two tools for semantic analysis.

The first combines Larissa aspects with another successful programming technique, design-by-contract [7], which has been originally introduced for object-oriented systems. There, a method is specified by a contract, which consists of an assumption clause and a guarantee clause. It fulfills its contract if after its execution, the guarantee holds whenever the assumption was true when the program was called.

Contracts have been adapted to reactive systems by [8], where assumptions and guarantees are expressed as observers, in the same way as Larissa pointcuts. Because reactive systems constantly receive inputs and emit outputs, it seems natural to let the assumption observer restrict the inputs, and let the guarantee observer ensure properties on the outputs.

Aspect-oriented programming and design-by-contract can hardly be used concurrently: when an aspect is applied to a method, it changes its semantics, such that its contract is no longer valid. The approach we present solves this problem for Argos and Larissa by generating a new contract that is valid after the application of the aspect. We show how to apply an aspect asp to a contract and derive a new contract , such that for any program which fulfills with asp fulfills . Although an observer is also an Argos program, we cannot directly apply aspects because it has a different interface where the outputs of the program have become inputs. We therefore transform the observers first into nondeterministic Argos programs, which produce exactly the execution traces the observer accepted, and apply the aspect to these. A second difficulty comes from the fact that we must treat assumption and guarantee differently to preserve the correctness of our algorithm. We demonstrate this approach on an example which models a tramway door controller.

The second semantic analysis we present treats interference between aspects. Applying several aspects to the same program may lead to unintended results because of conflicts between the aspects. We say that two aspects interfere when weaving them in different orders does not yield the same result.

Whether two aspects interfere depends on the way they are woven in the program. We distinguish sequential and joint weaving. Sequential weaving means weaving the aspects one by one, where the next aspect is woven in the result of the previous weaving. Argos operators are defined that way, and also Larissa aspects. On the other hand, joint weaving means weaving several aspects together, into the same base program. AspectJ is defined that way: its semantics is not defined as a transformation of the base program, but as injecting behavior in the running program, including other aspects.

Sequential weaving often causes interference between aspects because the second aspects is applied to the first, but not the other way round. Therefore, we present a joint weaving mechanism for Larissa, which applies aspects to the same base program, and thus reduces interferences. As opposed to AspectJ, however, all jointly woven aspects only affect the base program, but not each other. Therefore, we still need sequential weaving, in cases where one aspect needs to affect another.

Joint weaving removes many cases of interference, which we also demonstrate with an example. However, interference is unavoidable when two aspects want to modify the base program in the same point. Such cases should be made explicit to the programmer. We therefore present an interference analysis for jointly woven aspects, that can either determine that two aspects do not interfere for a given base program, or that they never interfere for any base program. In the first case, we apply both pointcuts to the base program and check if there are common join points. In the second case, it is sufficient to perform a parallel product of the two pointcuts. All these steps must be performed during the compilation process anyway, and thus add no additional cost.

Both tools that we present in this paper are only possible because of the semantic definition of Larissa. Thus the contract weaving can apply aspects to programs whose implementation is unknown. The interference analysis also depends on the semantic definition of Larissa, notably on the precise description of join points with observers, which makes it possible to determine statically the points where several aspects want to introduce their advice.

The structure of the paper is as follows: Section 2 introduces Larissa and Argos, Section 3 shows how to weave contracts in aspects, and Section 4 contains an example for this. Next, Section 5 explains the interference analysis, using a second example. Section 6 discusses related work, and Section 7 concludes. Work on the combination of contracts and aspects has been published in [9], and work on aspect interference in [10].

2. Argos and Larissa

This section presents a restriction of the Argos language [4], and the Larissa extension [5]. Argos is defined as a set of operators on complete and deterministic input/output automata communicating via Boolean signals. The semantics of an Argos program is given as a trace semantics that is common to a wide variety of reactive languages.

2.1. Traces and Trace Semantics

Definition 1 (Traces). Let be finite sets of Boolean input and output variables representing signals from and to the environment. An input trace, , is a function: . An output trace, , is a function: . One denotes by InputTraces (resp., OutputTraces) the set of all input (resp., output) traces. A pair of input and output traces (-traces for short) provides the valuations of every input and output at each instant . One denotes by (resp., ) the value of the input (resp., the output ) at the instant .

A set of pairs of -traces is deterministic if and only if for all , and it is complete if and only if for all .

A set of traces is a way to define the semantics of an Argos program , given its inputs and outputs. From the above definitions, a program is deterministic if from the same sequence of inputs it always computes the same sequence of outputs. It is complete whenever it allows every sequence of every eligible valuations of inputs to be computed. Determinism is related to the fact that the program is indeed written with a programming language (which has deterministic execution); completeness is an intrinsic property of the program that has to react forever, to every possible inputs without any blocking.

2.2. Argos

The core of Argos is made of input/output automata, the synchronous product, and the encapsulation. The synchronous product allows to put automata in parallel which synchronize on their common inputs, and the encapsulation is the operator that expresses the communication between automata. The semantics of an automaton is defined by a set of traces, and the semantics of the operators is given by translating expressions into flat automata.

Definition 2 (Automaton). An automaton is a tuple , where is the set of states, is the initial state, and are the sets of Boolean input and output variables, respectively, is the set of transitions. denotes the set of Boolean formulas with variables in . For , are the source and target states, is the triggering condition of the transition, and is the set of outputs emitted whenever the transition is triggered. Without loss of generality, we consider that automata only have complete monomials as input part of the transition labels.

The semantics of an automaton is given in terms of a set of pairs of -traces. This set is built using the following functions:(1) where returns the set of states that are reachable from state after performing steps with the input trace contains the different combinations of outputs that can be emitted at step after executing it from : (2)

Note that if the automaton is deterministic and complete, and always return a set with a single element.

We denote the set of all traces built following this scheme: defines the semantics of . The automaton is said to be deterministic (resp., complete) if and only if its set of traces is deterministic (resp., complete) (see Definition 1). Two automata are trace-equivalent, noted , if and only if . We assume that Argos programs are deterministic and complete, as these are important properties for reactive systems.

Definition 3 (Synchronous Product). Let and be automata. The synchronous product of and is the automaton , where is defined by (3)

The synchronous product of automata is both commutative and associative, and it is easy to show that it preserves both determinism and completeness.

Definition 4 (Encapsulation). Let be an automaton and be a set of inputs and outputs of . The encapsulation of w.r.t. is the automaton , where is defined by (4) where is the set of variables that appear as positive elements in the monomial (i.e., ). is the set of variables that appear as negative elements in the monomial (i.e., ). is then defined as .

Intuitively, a transition is still present in the result of the encapsulation operation if its label satisfies a local criterion made of two parts: means that a local variable which needs to be true has to be emitted by the same transition; means that a local variable that needs to be false should not be emitted in the transition. If the label of a transition satisfies this criterion, then the names of the encapsulated variables are hidden, both in the input part and in the output part. This is expressed by for the input part, and by for the output part. In general, the encapsulation operation does not preserve determinism nor completeness. This is related to the so-called “causality” problem intrinsic to synchronous languages (see, e.g., [3]).

2.2.1. An Example

Figure 1(a) shows a 3-bits counter. Dashed lines denote parallel compositions and the overall box denotes the encapsulation of the three parallel components, hiding signals and . The idea is the following: the first component on the right receives from the environment, and sends to the second one, every two 's. Similarly, the second one sends to the third one, every two 's. and are the carry signals. The global system has as input and as output; it counts 's modulo 8, and emits every 8 's. Applying the semantics of the operator (first the product of the three automata, then the encapsulation) yields the simple flat automaton with 8 states (Figure 1(b)).

Figure 1: A 3-bits counter. Notations: in each automaton, the initial state is denoted with a little arrow; the label on transitions are expressed by “/," for example, the transition labelled by “” is triggered when a is true and emits .
2.3. Larissa

Argos operators are already powerful. However, there are cases in which they are not sufficient to modularize all concerns of a program: a small modification of the global program's behavior may require that we modify all parallel components, in a way that is not expressible with the existing operators.

The goal of aspects being to specify such cross-cutting modifications, we proposed an aspect-oriented extension for Argos [5], which allows the modularization of a number of recurrent problems in reactive programs, like the reinitialization. This leads to the definition of a new operator (the aspect weaving operator), which preserves determinism and completeness of programs, as well as semantic equivalence between programs. Similar to aspects in other languages, a Larissa aspect consists of a pointcut, which selects a set of join points, and an advice, which modifies these join points.

2.3.1. Join Point Selection

To preserve semantical equivalence, pointcuts in Larissa are not expressed in terms of the internal structure of the base program (as, e.g., state names), but refer to the observable behavior of the program only, that is, its inputs and outputs. In the family of synchronous languages, where the communication between parallel components is the synchronous broadcast, observers [6] are a powerful and well-understood mechanism which may be used to describe pointcuts. Indeed, an observer is a program that may observe the inputs and the outputs of the base program, without modifying its behavior, and computes a safety property (in the sense of safety/liveness properties as defined in [11]).

Therefore, observers are well suited to express pointcuts. A pointcut is thus an observer which selects a set of join point transitions by emitting a single output JP, the join point signal. A transition in a program is selected as a join point transition when in the concurrent execution of and the pointcut, JP is emitted when is taken.

Technically, we perform a synchronous product between the program and the pointcut and select those transitions in the product which emit JP. However, if we simply put a program and an observer PC in parallel, 's outputs will become synchronization signals between them, as they are also inputs of PC. They will be encapsulated, and are thus no longer emitted by the product. We avoid this problem by introducing a new output for each output of will be used for the synchronization with PC, and will still be visible as an output. First, we transform into and PC into , where for all is replaced by . Second, we duplicate each output of by putting in parallel with one single-state automaton per output defined by . The complete product, where is noted , is given by (5) The join point transitions are those transitions of that emit . Figure 2 illustrates the pointcut mechanism. The pointcut (b) specifies any transition which emits : in base program (a), the loop transition in state is selected as a join point transition.

Figure 2: Example pointcut.
2.3.2. Specifying the Advice

In aspect-oriented languages, the advice expresses the modification applied to the base program. In Larissa, we define two types of advice: in the first type, an advice replaces the join point transitions with advice transitions pointing to an existing target states; in the second type, an advice introduces an Argos program between the source state of the join point transition and an existing target state. In both cases, target states have to be specified without referring explicitly to state names.

An advice adv has two ways of specifying the target state among the existing states of the base program is the state of that would be reached by executing a finite input trace from either the initial state of , adv is then called toInit advice, or from the source state of the join point transition, adv is then called toCurrent advice. As the base program is deterministic and complete, executing an input trace from any of its states defines exactly one state.

The advice weaving operator weaves a piece of advice adv in a program.

Advice Transitions

The first type of advice consists in replacing each join point transition with an advice transition. Once the target state is specified by a finite input trace , the only missing information is the label of these new transitions. We do not change the input part of the label, so as to keep the woven automaton deterministic and complete, but we replace the output part by some advice outputs . These are the same for every advice transition, and are thus specified in the aspect. Advice transitions are illustrated in Figure 3.

Figure 3: Schematic toInit and toCurrent aspects. Advice transitions are in bold, join point transitions are dotted.

Formal Definition

We only define toInit advice formally. A formal definition of the complete Larissa language can be found in [12, Chapter 4].

Definition 5 (ToInit Advice Weaving). Let be a deterministic and complete automaton and a piece of advice, with a finite input trace of length . The advice weaving operator, , weaves asp on and returns the automaton , where is defined as follows, with being the new target state: (6)(7)

Transitions (6) are not join point transitions and are left unchanged. Transitions (7) are the join point transitions, their final state targ is specified by the finite input trace . (which has been naturally extended to finite input traces) executes the trace during steps, from the initial state of .

Advice Programs

It is sometimes not sufficient to modify single transitions, that is, to jump to another location in the automaton in only one step. It may be necessary to execute arbitrary code when an aspect is activated. In these cases, we can insert an automaton between the join point and the target state.

Therefore, we use an inserted automaton that can terminate. Since Argos has no built-in notion of termination, the programmer of the aspect has to identify a final state (denoted by filled black circles in the figures).

We first specify a target state as explained above. Then, for every , a copy of the automaton is inserted, which means: (1) replace every join point transition with target state by a transition to the initial state of this instance of . As for advice transitions, the input part of the label is unchanged and the output part is replaced by ; (2) connect the transitions that went to the final state in to . Advice programs are illustrated in Figure 4.

Figure 4: Inserting an advice automaton.
2.3.3. Fully Specifying an Aspect

An aspect is given by the specification of its pointcut and its advice: , where PC is the pointcut and adv is the advice. adv is a tuple which contains (1) the advice outputs ; (2) the type of the target state specification (toInit or toCurrent); (3) the finite trace over the inputs of the program; and optionally, (4) , the advice program. Thus advice can be a tuple , or, with an advice program, a tuple , with . An aspect is woven into a program by first determining the join point transitions and then weaving the advice.

Definition 6 (Aspect Weaving). Let be a program and an aspect for . The weaving of asp on is defined by (8)

2.3.4. Example

As an example, consider a monostable flip-flop (MFF) with one input and one output , which emits two s after it received an . Figure 5(a) shows an implementation of the MFF in Argos. We want to make the MFF retriggerable, meaning that if an is emitted during several following instants, the MFF continues emitting . We do this by applying the aspect to the MFF, where is a pointcut which selects all occurrences of . as join points. Figure 5(b) shows the result of applyig to the implementation.

Figure 5: A mono stable flip-flop (a), made retriggerable (b).

3. Combining Contracts and Aspects

In this section, we show how to apply aspects to a specification of programs in form of a contract. First, we formally define contracts for Argos, then explain informally how to weave aspects into them, and finally define this process formally.

3.1. Contracts for Argos

The observers we use in contracts are slightly different from those used as pointcuts. Notably, once they start emitting their output err, they continue emitting it forever. This is done in an error state error. Such an observer specifies a class of programs fulfilling a certain safety property, namely, those programs where the observer never emits when combined with them. The error state is thus a way to refuse certain inputs while keeping the observer complete.

Definition 7 (Observer). An observer is an automaton which observes an automaton with inputs and outputs . When an observer emits , it will go to state error and also emit in the next instant. A program is said to obey an observer obs (noted ) if and only if produces no trace which emits .

Transitions leading to the error state are called error transitions.

A contract specifies a class of programs with two observers, an assumption and a guarantee. Definition 8 is an auxiliary definition, used to formally define contracts in Definition 9. denotes the trace for a single output that never emits , that is, for all . An observer that accepts a trace emits .

Definition 8 (Trace Combination). Let and be traces, with . Then, is a trace s.t. for all .

Definition 9 (Contract). A contract over inputs and outputs is a tuple of two observers over , where is the assumption and is the guarantee. A program fulfills a contract , written , if and only if (9)

Intuitively, a guarantee should only restrict the outputs of a program and an assumption should only restrict the inputs. We do not require this formally, but contracts which do not respect this constraint are of little use. Indeed, if restricts the inputs more than , it follows from Definition 9 that there exists no program s.t. . Conversely, a program is usually placed in an environment , s.t. . If restricts the outputs, no such exists, as the outputs are controlled by .

As an example for a contract, consider the following contract for the MFF from Section 2.3.4. The contract is composed of an assumption, shown in Figure 6(a), which states that 's always occur in pairs, and a guarantee consisting of two automata, shown in Figures 6(b) and 6(c), which are composed in parallel. The automaton in Figure 6(b) guarantees that single is never emitted, and the automaton in Figure 6(c) guarantees that when occurs while no is emitted, is emitted in the next instant. The product of Figures 6(b) and 6(c) is shown in Figure 6(d).

Figure 6: The contract for the MFF.
3.2. Weaving Aspects in Contracts

We want to apply an aspect asp not to a specific program , but to a class of programs defined by a contract , and obtain a new class of programs, defined by a contract , such that . To construct , we simulate the effect that the aspect has on a program as far as possible on the assumption and the guarantee observers of . However, an aspect cannot be applied directly to an observer because the aspect has been written for a program with inputs and outputs , whereas for the observer, are also inputs.

Therefore, we transform the observers of the contract first into nondeterministic automata (NDA), which produce exactly those traces that the observer accepts. We then weave the aspects into the NDA, with a modified definition of the weaving operator. The woven NDA are then transformed back into observers. The obtained observers may still be nondeterministic, and are thus determinized.

Except for aspect weaving, all of these steps are different for the assumption and the guarantee, as far as the Error transitions are concerned. This is because the assumption and the guarantee have different functions in a contract: the assumption states which part of the program is defined by the contract, and the guarantee gives properties that are always true for this part. Indeed, a contract can be rewritten as , where is an observer that emits when emits but not . Thus the assumption can be considered as a negated guarantee.

After weaving an aspect, the assumption must exclude the undefined part of any program which fulfills the contract. Therefore, it must reject a trace (by emitting ) as soon as there exists a program for which it cannot predict the behavior. The guarantee, on the other hand, emits only for traces which cannot be emitted by any program which fulfills the contract. Therefore, after weaving an aspect, the new guarantee may only emit if it is sure that there exists no program that produces the trace.

On the other hand, we want the assumption to be as permissive as possible, to include all possible programs, and the guarantee as restrictive as possible, to characterize the woven program as exactly as possible. Thus when we know exactly the behavior of the program, as, for example, that of an inserted advice program, we do not emit in the assumption, but we emit in the guarantee to exclude all input/output combinations that are never produced by the program.

3.3. Formal Definitions

This section describes the weaving of aspects into contracts in detail, and illustrates it on the MFF example. First, Definition 10 defines the transformation of an observer into an NDA through two functions, one for guarantee observers and one for assumption observers.

Definition 10 (Observer to NDA Transformation). Let be an observer with an error state Error over inputs and outputs , with . defines an NDA, where is defined by . defines an NDA, where is defined by .

Note that the transitions in obs which emit (i.e., the error transitions) have no corresponding transitions in . In the guarantee, these transitions correspond to input/output combinations which are never produced by the program and must not be considered by the aspect. The other transitions are transformed such that part of the condition concerning disappears, and those outputs that appeared as positive atoms in the condition (i.e., ) become outputs.

As an example, consider the guarantee of the MFF (Figure 6(d)). Its transformation into an NDA is shown in Figure 7(a). Note that the error state and the transitions leading to it have disappeared, and that is now an output. Thus the transition label has been transformed to , and label to .

Figure 7: (a) , (b) , (c) .

In the assumption, on the other hand, the error transition corresponds to inputs from the environment to which the program may react arbitrarily. If the aspect replaces these transitions in the assumption, they are also replaced in the program, and can thus be accepted from the environment by the woven program. Thus error transitions are not removed in , so that the aspect weaving can modify them. The transformation of the assumption of the MFF (Figure 6(a)) is shown in Figure 8(a).

Figure 8: (a) , (b) , (c) .

We can now apply an aspect to an NDA. However, a trace may lead to several states. Thus for each join point transition, several advice transitions must be created, one for each target state. We only give a definition for toInit advice, but the extension to toCurrent advice and advice programs is straightforward, and can be found in [12, Chapter 8].

Definition 11 (ToInit Weaving for NDA). Let be an automaton and a piece of toInit advice, with a finite input trace of length . The advice weaving operator , weaves adv into and returns the automaton , where is defined as follows: (10)(11)

Transitions (10) are not join point transitions and are left unchanged. Transitions (11) are the join point transitions, their final state targ is specified by the finite input trace . (which has been naturally extended to finite input traces) executes the trace during steps, from the initial state of . Figures 7(b) and 8(b) show the NDAs from our example with the retriggerable aspect from Section 2.3.4 woven into them. For both NDAs, the trace leads to a single state, thus only one advice transition is introduced per join point transition.

Transforming an NDA back into an observer is different for assumptions and guarantees. In the assumption, we do not add additional error transitions, but only leave those already there. In the guarantee, we add transitions to the error state from every state where the automaton is not complete. This is correct, as these transitions correspond to traces that are never produced by any program.

Definition 12 (NDA to Guarantee Transformation). Let be an NDA. defines an observer, where and are defined by (12) where and for a set of variables.

When transforming an NDA to an assumption, we do not add additional error transitions, but only leave those already there.

Definition 13 (NDA to Assumption Transformation). Let be an NDA. defines an observer, where is defined by (13)

Figures 7(c) and 8(c) show the NDAs from our example transformed back into observers. As expected, the obtained guarantee in Figure 7(c) tells us that whenever the program receives an , it emits 's the two following instants. The assumption, however, requires that if an is emitted, it continues to be emitted until there is no .

The resulting observer may not be deterministic. However, it can be made deterministic, as observers are acceptor automata. Determinization for guarantees and assumptions is different: a guarantee must only emit for a trace if all programs fulfilling the contract never emit , and an assumption must emit if there exists a program fulfilling the contract which is not defined for .

Existing determinization algorithms can be easily adapted to fulfill these requirements. We do not detail such algorithms here, but instead give conditions the determinization for assumptions and guarantees must fulfill. The new assumption and the new guarantee in the example are already deterministic, thus there is no need to determinize them.

The assumption determinization gives precedence to error transition. If there is a choice between an error transition and a nonerror transition, the error transition is always taken. Thus the determinized assumption only accepts a program if all possible nondeterministic executions of the nondeterminized assumption accept it.

Definition 14 (Assumption Determinization). Let be an NDA with outputs . is a deterministic automaton such that (14)

As opposed to the assumption determinization, the guarantee determinization gives precedence to nonerror transitions over error transitions. Thus the determinized guarantee emits only if all possible executions of the nondeterminized guarantee also emit .

Definition 15 (Guarantee Determinization). Let be an NDA with outputs . is a deterministic automaton such that (15)

We can now state the following theorem, which states that a contract constructed with the above operations holds indeed for any program fulfilling the original contract with an aspect applied to it.

Theorem 1. Let be a program and let be a contract. Then (16)

Theorem 1 first transforms the assumption and the guarantee into NDA with the respective operators, then applies the aspect to both and transforms the result back in observers, which are determinized. We prove it in Appendix A.

4. Example: The Tramway Door Controller

We implement and verify a larger example, taken from the Lustre tutorial [13], a controller of the door of a tramway. The door controller is responsible for opening the door when the tram stops and a passenger wants to leave the tram, and for closing the door when the tram wants to leave the station. Doors may also include a gangway, which can be extended to allow passengers in wheelchairs enter and leave the tram.

We implement the controller as an Argos program. We first develop a controller for a door without the gangway, and then add the gangway part with aspects. Table 1 gives the in- and outputs of the controller with their specifications, and also the in- and outputs which are added by the gangway. The controller uses additional inputs, called Helper Signals, which are also shown in Table 1 and are calculated from the original inputs.

Table 1: The interfaces of the controller and the gangway, and the helper signals.

It is important for the safety of the passengers that the doors are never open outside a station. We call this property , and formally express it as an observer that emits whenever is true. to formally verify this property, we must first develop a model that describes the possible behavior of the physical environment of the controller, which consists of the door and the tramway. These models are also expressed as Argos observers. The models for the tramway (called ) and the door (called ) are shown in Figures 9 and 10, respectively. These models require that the environment behaves correctly (e.g., the door only opens if has been emitted).

Figure 9: Model of the tramway, .
Figure 10: Model of the door, .

Furthermore, we give a contract for the door controller, which focuses on . The guarantee of the contract is shown in Figure 11, it ensures that the controller emits only if the doors are closed, and only if the tram is in a station. The contract has also an assumption , which is the model of the door given in Figure 10, that is, . An implementation of the controller, which fulfills the contract, is given in Figure 12.

Figure 11: The guarantee of the contract of the controller, .
Figure 12: A sample controller for the tramway door, .

We can now prove that the controller satisfies the contract (), and that the contract in the environment never violates the safety property. Formally, this is expressed as , where the synchronous product of observers means that the properties expressed by all the observers must be fulfilled.

4.1. Adding the Gangway

Two aspects are used to add support for the gangway: one aspect that extends the gangway before the door is opened if a passenger has asked for it, and one aspect that retracts the gangway when the tram is about to leave, if it is extended.

The pointcut of selects all transitions, where is true, and the pointcut of selects all transitions where is true.

Both aspects insert an automaton and return then to the initial state of the join point transitions. The inserted automata for the aspects are shown in Figure 13. is specified by , and by . Weaving these aspects into adds one state between and , where the gangway is retracted, and one state before , where it is extended.

Figure 13: Inserted automata for (a) and (b).
4.2. Modularly Verifying the Safety Properties

We want to check that the new controller still verifies the safety property from above, and also verifies two new safety properties, which require that the gangway is always fully retracted while the tram is out of station, and that the gangway is never moved when the door is not closed. We express these three properties as an observer and call it . To verify this, we first weave the aspects into the contract, and thus obtain a new contract that holds for controller with the aspects. Then we check that the environment, to which we added a model of the gangway , satisfies the new assumption (i.e., ), and that the new guarantee satisfies the safety requirements in the environment (i.e., ).

An alternative to this modular approach is to verify directly that the sample controller with the aspects does not violate the given safety properties (i.e., ). One disadvantage of the alternative approach is that the woven controller may be much bigger than the woven contract. To illustrate this problem, we verified the safety properties using our implementation [14]. The source code of the door controller example is available at [15]. Verifying the woven program takes 11.0 seconds. On the other hand, weaving the aspects into the guarantee of the controller contract and verifying against the environment takes 3.7 seconds, and verifying that the sample controller verifies the contract and verifying that the environment fulfills the assumption with the aspects takes 0.5 second. (Experiments were conducted on an Intel Pentium 4 with 2.4 GHz and 1 Gigabyte RAM.) Thus using this modular approach to verify the safety properties of the controller is significantly faster than verifying the complete program. Although the size of the woven controller is not prohibitive in this example, this indicates that larger programs can be verified using the modular approach.

5. Aspect Interference

A key point when dealing with aspects is the notion of interferences, which is closely related to the way aspects are woven. We illustrate the problem of interfering aspects on an example presented in Section 5.1. Next, we also present a new weaving algorithm in Section 5.2, that weaves aspects jointly, and removes aspect interferences in many cases. Finally, we introduce an algorithm in Section 5.3 that proves noninterference of aspects or identifies remaining interferences in jointly woven programs.

5.1. Example

As an example, we present a simplified view of the interface of a complex wristwatch, implemented with Argos and Larissa. The full case study was presented in [16]. The interface is a modified version of the Altimax model by Suunto. (Suunto and Altimax are trademarks of Suunto Oy.)

5.1.1. The Watch

The Altimax wristwatch has an integrated altimeter, a barometer and four buttons, the , the , the , and the button. Each of the main functionalities (time keeping, altimeter, barometer) has an associated main mode, which displays information, and a number of submodes, where the user can access additional functionalities. An Argos program that implements the interface of the watch is shown in Figure 14. For better readability, only those state names, outputs and transitions we will refer to are shown.

Figure 14: The Argos program for the Altimax watch.

In a more detailed model (as in [16]), the submode states would contain behavior using the refinement operator of Argos (see [4] for a definition). We do not present this operator in this paper since we do not need it to define aspect weaving. Adding refinement changes nothing for the weaving definition, as it works directly on the transformation of the program into a single trace-equivalent automaton. For the same reason, the interference analysis presented in Section 5.2 is also the same.

The buttons of the watch are the inputs of the program. The button circles between modes, the button selects the submodes. There are two more buttons: the and the button which modify current values in the submodes, but their effect is not shown in the figure. The buttons have different meanings depending on the mode in which the watch is currently.

The interface component we model here interprets the meaning of the buttons the user presses, and then calls a corresponding function in an underlying component. The outputs are commands to that component. For example, whenever the program enters the time mode, it emits the output , and the underlying component shows the time on the display of the watch.

5.1.2. Two Shortcut Aspects

The and the buttons have no function consistent with their intended meaning in the main modes: there are no values to increase or decrease. Therefore, they are given a different function in the main modes: when one presses the or the button in a main mode, the watch goes to a certain submode. The role of the and buttons in the main modes are called shortcuts since it allows to quickly activate a functionnality, which would have needed, otherwise, a long sequence of buttons.

Pressing the button in a main mode activates the function of the altimeter, and pressing the button activates the 4-day of the barometer. These functions are quite long to reach without the shortcuts since the logbook is the third submode of the altimeter, and the 4-day memory is the second submode of the barometer.

These shortcuts can be implemented easily with Larissa aspects. Figure 15(a) shows the pointcut for the logbook aspect, and Figure 15(b) the pointcut for the memory aspect. In both pointcuts, state represents the main modes and state represents the submodes. When, in a main mode, (resp., ) is pressed, the pointcut emits (resp., ), thus the corresponding advice is executed; when is pressed, the pointcut goes to the sub state, and or are no longer emitted. Furthermore, we use toInit advice with traces leading to the functionality we want to reach, that is, for the logbook aspect and for the 4-day memory aspect, and the output that tells the underlying component to display the corresponding information.

Figure 15: The pointcuts for the aspects.
5.2. Applying Several Aspects

If we apply first the logbook aspect, and then, sequentially, the memory aspect to the watch program, the aspects do not behave as we would expect. If, in the woven program, we first press the button in a main mode, thus activating the logbook aspect, and then the button, the memory aspect is activated, although we are in a submode. This behavior was clearly not intended by the programmer of the memory aspect.

The problem is that the memory aspect has been written for the program without the logbook aspect: the pointcut assumes that the only way to leave a main mode is to press the button. However, the logbook aspect invalidates that assumption by adding transitions from the main modes to a submode. When these transitions are taken, the pointcut of the memory aspect incorrectly assumes that the program is still in a main mode.

Furthermore, for the same reason, applying first the memory aspect and then the logbook aspect produces (in terms of trace-equivalence) a different program from applying first the logbook aspect and then the memory aspect: .

As a first attempt to define aspect interference, we say that two aspects and interfere when their application on a program in different orders does not yield two trace-equivalent programs: . We say that two aspects that do not interfere are independent.

With interfering aspects, the aspect that is woven second must know about the aspect that was applied first. To be able to write aspects as the ones above independently from each other, we propose a mechanism to weave several aspects at the same time. The idea is to first determine the join point transitions for all the aspects, and then apply the advice.

Definition 16 (Joint Weaving of Several Aspects). Let be some aspects, with , and a program. We define the application of on as follows: (17)

Note that Definition 16 reuses the advice weaving operator defined in Definition 5, and indexes the join point signal used by each advice. Furthermore, the advice is woven in the reverse order, that is, we first the advice from the last aspect in the aspect list, and the advice from the first aspect last. This way, aspects that are later in the list have higher priority: if a join point transition is claimed by several aspects, the one that is woven first replaces the join point transition with its advice transition, and removes the join point signals of the other aspects. To give priority to the aspects that are applied later is consistent with sequential weaving, where aspects that are applied later modify the aspects that have already been applied, but not the other way round.

Jointly weaving the logbook and the memory aspect leads to the intended behavior, that is, both aspects can be activated only when the program is in a main mode. Furthermore, the weaving order does not influence the result because both aspects first select their join point transitions in the main modes, and change the target states of the join point transitions only afterwards.

Note that Definition 16 does not make sequential weaving redundant. We still need to weave aspects sequentially in some cases, when the second aspects must be applied to the result of the first. For instance, imagine an aspect that adds an additional main mode to the watch. Then the shortcut aspects must be sequentially woven after this aspect, so that they can select the new main mode as join point.

Definition 16 does not solve all conflicts. Indeed, the in do not commute, in general, since the advice weaving is applied sequentially. We define aspect interference for the application of several aspects.

Definition 17 (Aspect Interference). Let be some aspects, and a program. We say that and interfere for if and only if (18)

As an example for interfering aspects, assume that the condition of the join point transition of the pointcut of the logbook aspect (Figure 15(a)) is only and the condition of the join point transition of the pointcut of the logbook aspect (Figure 15(b)) is only . In this case, the two aspects share some join point transitions, namely, when both buttons are pressed at the same time in a main mode. Both aspects then want to execute their advice, but only one can, thus they interfere. Only the aspect that was applied last is executed.

In such a case, the conflict should be made explicit to the programmer, so that it can be solved by hand. Here, it was resolved by changing the pointcuts to the form they have in Figure 15, so that neither aspect executes when both buttons are pressed.

5.3. Proving Noninterference

In this section, we show that in some cases, noninterference of aspects can be proven, if the aspects are woven jointly, as defined in Definition 16. We can prove noninterference of two given aspects either for any program, or for a given program. Following [17], we speak of strong independence in the first case, and of weak independence in the second.

We use the operator jpTrans to determine interference between aspects. It computes all the join point transitions of an automaton, that is, all transitions with a given output .

Definition 18. Let be an automaton and . Then (19)

The following theorem proves strong independence between two aspects.

Theorem 2 (Strong Independence). Let be some aspects, with . Then the following equation holds: (20)

See Appendix B for a proof. Theorem 2 states that if there is no transition with both and as outputs in the product of and , and are independent and thus can commute while weaving their advice. Theorem 2 defines a sufficient condition for noninterference, by looking only at the pointcuts. When the condition holds, the aspects are said to be strongly independent.

Theorem 3 (Weak Independence). Let be some aspects, with , and . Then the following equation holds: (21)

See Appendix C for a proof. Theorem 3 states that if there is no transition with both and as outputs in and do not interfere. This is weaker than Theorem 2 since it also takes the program into account. However, there are cases in which the condition of Theorem 2 is false (thus it yields no results), but Theorem 3 allows to prove noninterference, for example, in the case of the gangway aspects from Section 4, which is discussed in Section 5.3.2.

Theorem 3 is a sufficient condition, but, as Theorem 2, it is not necessary: it may not be able to prove independence for two independent aspects. The reason is that it does not take into account the effect of the advice weaving: consider two aspects such that the only reason why the condition for Theorem 3 is false is a transition sourced in some state , and such that is only reachable through another join point transition; if the advice weaving makes this state unreachable, then the aspects do not interfere.

The results obtained by both Theorems are quite intuitive. They mean that if the pointcuts do not select any join points common to two aspects, then these aspects do not interfere. This condition can be calculated on the pointcuts alone, or can also take the program into account.

Note that the detection of noninterference is a static condition that does not add any complexity overhead. Indeed, to weave the aspects, the compiler needs to build first : the condition of Theorem 2 can be checked during the construction of . Second, the weaver builds . Afterwards, it can check the condition of Theorem 3. Thus to calculate the conditions of both Theorems, it is sufficient to check the outputs of the transitions of intermediate products during the weaving. The weaver can easily emit a warning when a potential conflict is detected.

To have an exact characterization of noninterference, it is still possible to compute the predicate , but calculating semantic equality is very expensive for large programs.

Note that the interference presented here only applies to the joint weaving of several aspects, as defined in Definition 16. Sequentially, woven aspects may interfere even if their join points are disjoint, because the pointcut of the second aspects applies to the woven program. A similar analysis to prove noninterference of sequential weaving would be more difficult because the effect of the advice must be taken into account. Indeed, the advice of an aspect influences which transitions are selected by the pointcut of an aspect that is sequentially woven next.

5.3.1. Interference between the Shortcut Aspects

Figure 16(a) shows the product of the pointcuts of the logbook (Figure 15(a)) and the memory aspect (Figure 15(b)). There are no transitions that emit both and , thus, by applying Theorem 2, we know that the aspects do not interfere, independently of the program they are applied to.

Figure 16: Interference between pointcuts.

Let us assume again that the condition of the join point transition of the pointcut of the logbook aspect (Figure 15(a)) is only and the condition of the join point transition of the pointcut of the logbook aspect (Figure 15(b)) is only . In this case, the state main in Figure 16(a) would have another loop transition, with label . Thus, Theorem 2 not only states that the aspects potentially interfere, but it also states precisely where: here, the problem is that when both and are pressed in a main mode, at the same time, both aspects are activated. Larissa thus emits a warning and the user can solve the conflict.

5.3.2. Interference between the Gangway Aspects

As an example for weak interference, let us examine the gangway aspects from the Tram example in Section 4. Figure 16(b) shows the product of their pointcuts. There is a transition that has both and as outputs. Theorem 2 states that the aspects may interfere, but when applied to the tram controller from Figure 12, they do not. This is because and are outputs of the controller, and are never emitted at the same time.

In this example, the use of Theorem 3 is thus needed to show that the aspects do not interfere when applied to the wristwatch controller. As expected, and are never emitted at the same time in , and Theorem 3 thus shows that the aspects do not interfere for this base program.

6. Related Work

6.1. Contracts and Aspects

Goldman and Katz [18] modularly verify aspect-oriented programs using an LTL tableau representation of programs and aspects. As opposed to ours, their system can verify AspectJ aspects, as tools like Bandera [19] can extract suitable input models from Java programs. It is, however, limited to the so-called weakly invasive aspects, which only return to states already reachable in the base program.

Clifton and Leavens [20] noted before us that aspects invalidate the specification of modules, and propose that either an aspect should not modify a program's contract, or that modules should explicitly state which aspects may be applied to them.

6.2. Aspect Interference

Some authors discuss the advantages of sequential versus joint weaving. Lopez-Herrejon and Batory [21] propose to use sequential weaving for incremental software development. Colyer and Clement [22, Section 5.1] want to apply aspects to bytecode which already contains woven aspects. In AspectJ, this is impossible because the semantics would not be the same as weaving all aspects at the same time.

Sihman and Katz [23] propose SuperJ, a superimposition language which is implemented through a preprocessor for AspectJ. They propose to combine superimpositions into a new superimposition, either by sequentially applying one to the other, or by combining them without mutual influence. Superimpositions contain assume/guarantee contracts, which can be used to check if a combination is valid.

A number of authors investigate aspect interference in different formal frameworks. Much of the work is devoted to determining the correct application order for interfering aspects, whereas we focus on proving noninterference.

Douence et al. [17] present a mechanism to statically detect conflicts between aspects that are applied in parallel. Their analysis detects all join points where two aspects want to insert advice. To reduce the detection of spurious conflicts, they extend their pointcuts with shared variables, and add constraints that an aspect can impose on a program. To resolve remaining conflicts, the programmer can then write powerful composition adaptors to define how the aspects react in presence of each other.

Pawlak et al. [24] present a way to formally validate precedence orderings between aspects that share join points. They introduce a small language, CompAr, in which the user expresses the effect of the advice that is important for aspect interaction, and properties that should be true after the execution of the advice. The CompAr compiler can then check that a given advice ordering does not invalidate a property of an advice.

Dur et al. [25] propose an interaction analysis for composition filters. They detect when one aspect prevents the execution of another, and can check that a specified trace property is ensured by an aspect.

Balzarotti et al. [26] use program slicing to check if different aspects modify the same code, which might indicate interference.

7. Conclusion

We presented two formal analysis tools for Larissa, which both exploit its semantic definition. The first combines Larissa with design-by-contract, and shows exactly how a Larissa aspect modifies the contract of a component to which it is applied. This allows us to calculate the effect of an aspect on a specification instead of only on a concrete program. This approach has several advantages. First, aspects can be checked against contracts even if the final implementation is not yet available during development. Furthermore, if the base program is changed, the woven program must not be reverified, as long as the new base program still fulfills the contract. Finally, woven programs can be verified modularly, which may allow to verify larger programs.

The second approach is an analysis for aspect interference in Larissa. We introduced an additional operator which jointly weaves several aspects together into a program, closer to the way AspectJ weaves aspects. Because Larissa is defined modularly, we only had to rearrange the building steps of the weaving process. Then we could analyze interference with a simple parallel product of the pointcuts. When a potential conflict is detected, the user has to solve it by hand, if needed. In the examples we studied, the conflicts were solved by simple modifications of the pointcuts.

These analyses are only possible because Argos and Larissa are very simple languages with clean and simple semantics. They thus illustrate the advantage of using a programming language with simple semantics. Because of this simplicity, both approaches seem quite precise. Indeed, We believe that the contract weaving is exact in that it gives no more possible behaviors for the woven program than necessary. That is, for a contract C and a trace , there exists a program s.t. and . This remains however to be proven.

The interference analysis for Larissa seems also quite precise, that is, we can prove independence for most independent aspects. One reason for that are Larissa's powerful pointcuts, which describe join points statically, yet very precisely, on the level of transitions. Another reason is the exclusive nature of the advice. Two pieces of advice that share a join point transition never execute sequentially, but there is always one that is executed while the other is not. If the two pieces of advice are not equivalent, this leads to a conflict. Thus as opposed to [17], assuming that a shared join point leads to a conflict does not introduce spurious conflicts.

There are some interesting points for further work. In the context of contract weaving, an interesting question is if we can derive contracts the other way round. Given a contract and an aspect asp, can we automatically derive a contract such that ? Finally, both approaches work only because we have restricted Argos and Larissa to Boolean signals. It would be interesting to see if they can be extended to programs with variables.

Appendices

A. Proof for Theorem 1

Definitions

We first introduce a number of definitions.

means that program fulfills contract , where the initial states of , and have been set to , and , respectively.

Furthermore, we introduce the following notations for terms from the theorem. Let (A.1) We now define the structure of some of these terms. Let (A.2)

We prove the theorem by induction over a trace of . Let . We show that the following induction hypothesis holds for any .

Induction Hypothesis

The induction hypothesis states that the states reached by executing on , , and formed a valid contract in and , that is, before the aspect was applied, provided is accepted by . Formally, we write it as follows: (A.3) and are the states reached when executing for steps on and , respectively.

Base Case

holds as it is the assumption of the implication in the theorem. If the initial state of is the error state, either (and ) do not accept any trace, or no exists, and in both cases we are done.

Induction Step

From to .

If , we are done. Otherwise, from follows because Definition 14, which defines the determinization of , gives precedence to error transitions. We distinguish two cases as follows.

(i) First case: , we are not in a join point. Because of , there is a transition in , a transition in , and a transition in , such that and are not modified by the weaving, thus there is a transition in , a transition in , and a transition in with .

(ii) Second case: , we are in a join point. Let be the state in the reached after executing , and let be a trace of length such that for all . Then let be the state of the pointcut reached after executing . Then we also have . All join point transitions in (resp., ) are replaced by transitions to all possible target states, thus there is a transition (resp., ) to a target state (resp., ) such that (resp., ). Because and can be reached with the same trace (resp., for and ) from the initial state, follows from . Furthermore, , and we have , and , and thus and . Furthermore, we have , as otherwise (impossible because of ), or , by the definition of .

It follows from the induction hypothesis that (A.4) and we have by Definition 15. Thus the theorem follows from the induction hypothesis.

B. Proof for Theorem 2

Theorems 2 and 3 are both implications with the same consequent.

We show that the antecedent of the implication in Theorem 3, (B.5) follows from the antecedent of the implication in Theorem 2, (B.6) and can only occur in and . Thus if a transition that has both of them as outputs in , there must already exist a transition with both of them as outputs in .

Thus because of the transitivity of the implication, Theorem 2 is a consequence of Theorem 3.

C. Proof for Theorem 3

Because the synchronous product is commutative and are the same.

Let . Then yields an automaton , where is defined as follows: (C.7) and yields an automaton , where is defined as follows: (C.8)(C.9)

If we calculate , we obtain the same automaton, except for transitions (C.9), which are defined by (C.10)

Transitions (C.9) are exactly the join point transitions that are in . By precondition, there were no such transitions in . Because we require that all the outputs occur nowhere else, and cannot be contained in a , thus no transition of type (C.9) has been added by the weaving of .

Thus we have . Weaving trivially yields the same result.

References

  1. G. Kiczales, E. Hilsdale, J. Hugunin, M. Kersten, J. Palm, and W. G. Griswold, “An oerview of aspectJ,” in Proceedings of the 15th European Conference on Object-Oriented Programming (ECOOP '01), vol. 2072 of Lecture Notes in Computer Science, pp. 327–354, Budapest, Hungary, June 2001.
  2. N. Halbwachs, Synchronous Programming of Reactive Systems, Kluwer Academic Publishers, Norwell, Mass, USA, 1993.
  3. G. Berry and G. Gonthier, “The ESTEREL synchronous programming language: design, semantics, implementation,” Science of Computer Programming, vol. 19, no. 2, pp. 87–152, 1992.
  4. F. Maraninchi and Y. Rémond, “Argos: an automaton-based synchronous language,” Computer Languages, vol. 27, no. 1–3, pp. 61–92, 2001.
  5. K. Altisen, F. Maraninchi, and D. Stauch, “Aspect-oriented programming for reactive systems: Larissa, a proposal in the synchronous framework,” Science of Computer Programming, vol. 63, no. 3, pp. 297–320, 2006.
  6. N. Halbwachs, F. Lagnier, and P. Raymond, “Synchronous observers and the verification of reactive systems,” in Proceedings of the 3rd International Conference on Methodology and Software Technology: Algebraic Methodology and Software Technology (AMAST '93), M. Nivat, C. Rattray, T. Rus, and G. Scollo, Eds., pp. 83–96, Enschede, The Netherlands, June 1993.
  7. B. Meyer, “Applying ‘design by contract’,” Computer, vol. 25, no. 10, pp. 40–51, 1992.
  8. F. Maraninchi and L. Morel, “Logical-time contracts for reactive embedded components,” in Proceedings of the 30th Euromicro Conference on Component-Based Software Engineering Track (ECBSE '04), pp. 48–55, Rennes, France, August-September 2004.
  9. D. Stauch, “Modifying contracts with Larissa aspects,” in Proceedings of the Workshop on Model-Driven High-Level Programming of Embedded Systems (SLA++P '07), Braga, Portugal, March 2007.
  10. D. Stauch, K. Altisen, and F. Maraninchi, “Interference of Larissa aspects,” in Proceedings of the Foundations of Aspect-Oriented Languages Workshop (FOAL '06), pp. 57–65, Bonn, Germany, March 2006.
  11. L. Lamport, “Proving the correctness of multiprocess programs,” IEEE Transactions on Software Engineering, vol. 3, no. 2, pp. 125–143, 1977.
  12. D. Stauch, Larissa, an aspect-oriented language for reactive systems, Ph.D. thesis, Institut Nationale Polytechnique de Grenoble, Grenoble Cedex, France, November 2007.
  13. The Lustre tutorial, http://www-verimag.imag.fr/~raymond/edu/tp.ps.gz.
  14. Compiler for Larissa, http://www-verimag.imag.fr/~stauch/ArgosCompiler.
  15. Argos source code for the tram example, http://www-verimag.imag.fr/~stauch/ArgosCompiler/contracts.html.
  16. K. Altisen, F. Maraninchi, and D. Stauch, “Modular design of man-machine interfaces with Larissa,” in Proceedings of the 5th International Symposium on Software Composition (SC '06), pp. 291–306, Vienna, Austria, March 2006.
  17. R. Douence, P. Fradet, and M. Südholt, “Composition, reuse and interaction analysis of stateful aspects,” in Proceedings of the 3rd International Conference on Aspect-Oriented Software Development (AOSD '04), K. Lieberherr, Ed., pp. 141–150, Lancaster, UK, March 2004.
  18. M. Goldman and S. Katz, “Modular generic verification of LTL properties for aspects,” in Proceedings of the Foundations of Aspect-Oriented Languages Workshop (FOAL '06), Bonn, Germany, March 2006.
  19. J. C. Corbett, M. B. Dwyer, J. Hatcliff, et al., “Bandera: extracting finite-state models from Java source code,” in Proceedings of the 22nd International Conference on Software Engineering (ICSE '00), pp. 439–448, Limerick, Ireland, June 2000.
  20. C. Clifton and G. T. Leavens, “Obliviousness, modular reasoning, and the behavioral subtyping analogy,” Department of Computer Science, Iowa State University, Ames, Iowa, USA, December 2003.
  21. R. E. Lopez-Herrejon and D. Batory, “Improving incremental development in AspectJ by bounding quantification,” in Proceedings of the Software-Engineering Properties of Languages and Aspect Technologies Workshop (SPLAT '05), L. Bergmans, K. Gybels, P. Tarr, and E. Ernst, Eds., Chicago, Ill, USA, March 2005.
  22. A. Colyer and A. Clement, “Large-scale AOSD for middleware,” in Proceedings of the 3rd International Conference on Aspect-Oriented Software Development (AOSD '04), K. Lieberherr, Ed., pp. 56–65, Lancaster, UK, March 2004.
  23. M. Sihman and S. Katz, “Superimpositions and aspect-oriented programming,” The Computer Journal, vol. 46, no. 5, pp. 529–541, 2003.
  24. R. Pawlak, L. Duchien, and L. Seinturier, “CompAr: ensuring safe around advice composition,” in Proceedings of the 7th IFIP International Conference on Formal Methods for Open Object-Based Distributed Systems (FMOODS '05), vol. 3535 of Lecture Notes in Computer Science, pp. 163–178, Athens, Greece, June 2005.
  25. P. Durr, T. Staijen, L. Bergmans, and M. Aksit, “Reasoning about semantic conflicts between aspects,” in Poceedings of the 2nd European Interactive Workshop on Aspects in Software (EIWAS '05), K. Gybels, M. D'Hondt, I. Nagy, and R. Douence, Eds., Brussels, Belgium, September 2005.
  26. D. Balzarotti, A. C. D'Ursi, L. Cavallaro, and M. Monga, “Slicing aspectJ woven code,” in Proceedings of the Foundations of Aspect-Oriented Languages Workshop (FOAL '05), G. T. Leavens, C. Clifton, and R. Lämmel, Eds., Chicago, Ill, USA, March 2005.