Verimag, Centre Équation 2, Avenue de Vignate, 38610 Gières, France
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
- 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.
- N. Halbwachs, Synchronous Programming of Reactive Systems, Kluwer Academic Publishers, Norwell, Mass, USA, 1993.
- G. Berry and G. Gonthier, “The synchronous programming language: design, semantics, implementation,” Science of Computer Programming, vol. 19, no. 2, pp. 87–152, 1992.
- F. Maraninchi and Y. Rémond, “Argos: an automaton-based synchronous language,” Computer Languages, vol. 27, no. 1–3, pp. 61–92, 2001.
- 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.
- 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.
- B. Meyer, “Applying ‘design by contract’,” Computer, vol. 25, no. 10, pp. 40–51, 1992.
- 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.
- 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.
- 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.
- L. Lamport, “Proving the correctness of multiprocess programs,” IEEE Transactions on Software Engineering, vol. 3, no. 2, pp. 125–143, 1977.
- D. Stauch, Larissa, an aspect-oriented language for reactive systems, Ph.D. thesis, Institut Nationale Polytechnique de Grenoble, Grenoble Cedex, France, November 2007.
- The Lustre tutorial, http://www-verimag.imag.fr/~raymond/edu/tp.ps.gz.
- Compiler for Larissa, http://www-verimag.imag.fr/~stauch/ArgosCompiler.
- Argos source code for the tram example, http://www-verimag.imag.fr/~stauch/ArgosCompiler/contracts.html.
- 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.
- 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.
- 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.
- 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.
- 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.
- 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.
- 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.
- M. Sihman and S. Katz, “Superimpositions and aspect-oriented programming,” The Computer Journal, vol. 46, no. 5, pp. 529–541, 2003.
- 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.
- 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.
- 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.