Action Language For Foundational UML
Action Language For Foundational UML
____________________________________________________
OMG Document Number: ptc/2010-10-05
Standard document URL: http://www.omg.org/spec/ALF/1.0
Associated File(s)*: http://www.omg.org/spec/ALF/20100801
http://www.omg.org/spec/ALF/20100802
http://www.omg.org/spec/ALF/20100803
____________________________________________________
*original files: ad/2010-08-02 (XMI), ad/2010-08-03 (Abstract Syntax XMI), ad/2010-08-10
(Action Language Profile XMI)
This OMG document replaces the submission document (ad/2010-08-01, Alpha). It is an OMG
Adopted Beta Specification and is currently in the finalization phase. Comments on the content
of this document are welcome, and should be directed to [email protected] by June 13, 2011.
You may view the pending issues for this specification from the OMG revision issues web page
http://www.omg.org/issues/.
The FTF Recommendation and Report for this specification will be published on August 22,
2011. If you are reading this after that date, please download the available specification from the
OMG Specifications Catalog.
Copyright © 2010 Data Access Technologies, Inc. (Model Driven Solutions)
Copyright © 2010 Mentor Graphics Corporation
Copyright © 2010 International Business Machines
Copyright © 2010 88solutions Corporation
Copyright © 2010 No Magic, Inc.
Copyright © 2010 Visumpoint
Copyright © 2010 Object Management Group
LICENSES
The companies listed above have granted to the Object Management Group, Inc. (OMG) a nonexclusive, royalty-
free, paid up, worldwide license to copy and distribute this document and to modify this document and distribute
copies of the modified version. Each of the copyright holders listed above has agreed that no person shall be deemed
to have infringed the copyright in the included material of any such copyright holder by reason of having used the
specification set forth herein or having conformed any computer software to the specification.
Subject to all of the terms and conditions below, the owners of the copyright in this specification hereby grant you a
fully-paid up, non-exclusive, nontransferable, perpetual, worldwide license (without the right to sublicense), to use
this specification to create and distribute software and special purpose specifications that are based upon this
specification, and to use, copy, and distribute this specification as provided under the Copyright Act; provided that:
(1) both the copyright notice identified above and this permission notice appear on any copies of this specification;
(2) the use of the specifications is for informational purposes and will not be copied or posted on any network
computer or broadcast in any media and will not be otherwise resold or transferred for commercial purposes; and (3)
no modifications are made to this specification. This limited permission automatically terminates without notice if
you breach any of these terms or conditions. Upon termination, you will destroy immediately any copies of the
specifications in your possession or control.
PATENTS
The attention of adopters is directed to the possibility that compliance with or adoption of OMG specifications may
require use of an invention covered by patent rights. OMG shall not be responsible for identifying patents for which
a license may be required by any OMG specification, or for conducting legal inquiries into the legal validity or
scope of those patents that are brought to its attention. OMG specifications are prospective and advisory only.
Prospective users are responsible for protecting themselves against liability for infringement of patents.
WHILE THIS PUBLICATION IS BELIEVED TO BE ACCURATE, IT IS PROVIDED "AS IS" AND MAY
CONTAIN ERRORS OR MISPRINTS. THE OBJECT MANAGEMENT GROUP AND THE COMPANIES
LISTED ABOVE MAKE NO WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, WITH REGARD TO
THIS PUBLICATION, INCLUDING BUT NOT LIMITED TO ANY WARRANTY OF TITLE OR OWNERSHIP,
IMPLIED WARRANTY OF MERCHANTABILITY OR WARRANTY OF FITNESS FOR A PARTICULAR
PURPOSE OR USE. IN NO EVENT SHALL THE OBJECT MANAGEMENT GROUP OR ANY OF THE
COMPANIES LISTED ABOVE BE LIABLE FOR ERRORS CONTAINED HEREIN OR FOR DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, CONSEQUENTIAL, RELIANCE OR COVER DAMAGES, INCLUDING
LOSS OF PROFITS, REVENUE, DATA OR USE, INCURRED BY ANY USER OR ANY THIRD PARTY IN
CONNECTION WITH THE FURNISHING, PERFORMANCE, OR USE OF THIS MATERIAL, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
The entire risk as to the quality and performance of software developed using this specification is borne by you. This
disclaimer of warranty constitutes an essential part of the license granted to you to use this specification.
TRADEMARKS
MDA®, Model Driven Architecture®, UML®, UML Cube logo®, OMG Logo®, CORBA® and XMI® are
registered trademarks of the Object Management Group, Inc., and Object Management Group™, OMG™ , Unified
Modeling Language™, Model Driven Architecture Logo™, Model Driven Architecture Diagram™, CORBA
logos™, XMI Logo™, CWM™, CWM Logo™, IIOP™ , MOF™ , OMG Interface Definition Language (IDL)™ ,
and OMG SysML™ are trademarks of the Object Management Group. All other products or company names
mentioned are used for identification purposes only, and may be trademarks of their respective owners.
COMPLIANCE
The copyright holders listed above acknowledge that the Object Management Group (acting itself or through its
designees) is and shall at all times be the sole entity that may authorize developers, suppliers and sellers of computer
software to use certification marks, trademarks or other special designations to indicate compliance with these
materials.
Software developed under the terms of this license may claim compliance or conformance with this specification if
and only if the software compliance is of a nature fully matching the applicable compliance points as stated in the
specification. Software developed only partially matching the applicable compliance points may claim only that the
software was based on this specification, but may not claim compliance or conformance with this specification. In
the event that testing suites are implemented or approved by Object Management Group, Inc., software developed
using this specification may claim compliance or conformance with the specification only if the software
satisfactorily completes the testing suites.
OMG’s Issue Reporting Procedure
All OMG specifications are subject to continuous review and improvement. As part of this process we encourage
readers to report any ambiguities, inconsistencies, or inaccuracies they may find by completing the Issue Reporting
Form listed on the main web page http://www.omg.org, under Documents, Report a Bug/Issue
(http://www.omg.org/technology/agreement.)
Contents
Preface........................................................................................................................................................xi
PART I - INTRODUCTION.....................................................................................................................1
1 Scope.........................................................................................................................................................1
2 Conformance...........................................................................................................................................2
2.1 Syntactic Conformance......................................................................................................................2
2.2 Semantic Conformance......................................................................................................................2
2.3 Additional Conformance Points.........................................................................................................3
3 Normative References.............................................................................................................................4
4 Terms and Definitions............................................................................................................................5
5 Symbols....................................................................................................................................................6
6 Overview..................................................................................................................................................7
6.1 Integration with UML Models...........................................................................................................7
6.2 Templates...........................................................................................................................................8
6.3 Lexical Structure..............................................................................................................................10
6.4 Concrete Syntax...............................................................................................................................11
6.5 Abstract Syntax................................................................................................................................13
6.6 Mapping to Foundational UML.......................................................................................................14
6.7 Organization of the Specification....................................................................................................14
6.8 Acknowledgments............................................................................................................................15
PART II - LANGUAGE DESCRIPTION.............................................................................................16
7 Lexical Structure...................................................................................................................................16
7.1 Line Terminators..............................................................................................................................16
7.2 Input Elements and Tokens..............................................................................................................16
7.3 White Space.....................................................................................................................................17
7.4 Comments........................................................................................................................................17
7.4.1 Lexical Comments....................................................................................................................17
7.4.2 Documentation Comments........................................................................................................18
7.5 Names..............................................................................................................................................18
7.6 Reserved Words...............................................................................................................................21
7.7 Primitive Literals.............................................................................................................................21
7.7.1 Boolean Literals........................................................................................................................21
7.7.2 Natural Literals.........................................................................................................................21
7.7.3 Unbounded Value Literals........................................................................................................23
7.7.4 String Literals............................................................................................................................23
7.8 Punctuation......................................................................................................................................24
7.9 Operators..........................................................................................................................................24
8 Expressions............................................................................................................................................25
8.1 Overview..........................................................................................................................................25
8.2 Qualified Names..............................................................................................................................27
8.3 Primary Expressions........................................................................................................................32
OMG Specifications
As noted, OMG specifications address middleware, modeling and vertical domain frameworks. A
Specifications Catalog is available from the OMG website at:
http://www.omg.org/technology/documents/spec_catalog.htm
Specifications within the Catalog are organized by the following categories:
Typographical Conventions
The type styles shown below are used in this document to distinguish programming statements from
ordinary English. However, these conventions are not used in tables or section headings where no
distinction is necessary.
Times/Times New Roman - 10 pt.: Standard body text
Helvetica/Arial - 10 pt. Bold: OMG Interface Definition Language (OMG IDL) and syntax elements.
Courier - 10 pt. Bold: Programming language elements.
Note that the qualified name for an element is determined by its owning namespace. Therefore, even
though the name “Integer” resolves in Alf to “Alf::Library::PrimitiveTypes:: Integer”, this
element is just an import of “UML::AuxiliaryTypes::PrimitiveTypes:: Integer” (see Subclause
11.2), and it is the latter qualified name that is used.
Since the initial copy of the template model element also copies the reference to the namespace of the
original template, the equivalent bound element is considered to be added to that namespace. A
modeling environment must disallow any user-created element in a namespace with template elements
with a name that would conflict with a standard equivalent bound element name created as defined
above.
NOTE. The concept of equivalent bound elements defined above is intended to provide a specification
of the semantics of template instantiation compatible with execution semantics that are defined only on
the fUML subset. It is not required that a conforming implementation actually physically generate
equivalent bound elements in order to execute Alf text, particularly if that implementation semantically
conforms through interpretive or translational execution (see Subclause 2.2). However, an
implementation that conforms through compilative execution must produce a UML model conforming
to the fUML subset, in which case the implementation would, in fact, need to replace templates and
bindings with equivalent elements as described here (or similar elements with an equivalent effect, as
discussed in Subclause 2.2).
* The escape sequences given in Table 7-3 are also used to represent the corresponding special
characters within terminal elements in the EBNF notation.
According to this production, a NameDeclaration may have one of two alternative forms:
• The terminal element “let”, followed by a Name (a lexical token whose string image is assigned to
the name property of object s), followed by a “:”, followed by a TypeName (whose value is assigned
to s.typeName), optionally followed by a MultiplicityIndicator (if there is a
MultiplicityIndicator, then s.hasMultiplicity must be true).
In this case, the first name is assigned to the property q.name, and then subsequent names, if any, are
appended as additional values of that same property. Clearly, for this to be valid, the property
QualifiedName::name must have a multiplicity upper bound of *.
Technically, the Alf concrete syntax is specified (as described above) using a simplified form of an
attributive grammar. Each production has a single synthesized attribute. In an attributive grammar, the
values for synthesized attributes are passed upwards in the parse tree. The Alf concrete grammar does
not include any inherited attributes, however. Inherited attributes are passed downwards in the parse tree
in order to enforce context-sensitive constraints. For Alf, such constraints are instead specified on the
abstract syntax representation after parsing.
6.8 Acknowledgments
The following people from the various submitting organizations contributed to this specification:
• Ed Seidewitz, Model Driven Solutions
• Kim Letkeman, IBM
• Stephen Mellor, Mentor Graphics
• Manfred Koethe, 88 Solutions
• Nerijus Jankevicius, No Magic
We would also like to acknowledge Doug Tolbert, CSC, for his thorough review of the specification as
the head of the Evaluation Working Group.
Cross References
1. WhiteSpace see Subclause 7.3
2. LexicalComment see Subclause 7.4.1
3. DocumentationComment see Subclause 7.4.2
4. Name see Subclause 7.5
Cross References
1. LineTerminator see Subclause 7.1
7.4 Comments
Comments are used to annotate other elements of the input text. They have no computable semantics, but
simply provide information useful to a human reader of the text. There are three kinds of comments.
• An end-of-line comment includes all the text from the initial characters “//” to the end of the
line, except that “//@” begins a statement annotation rather than a comment (see Subclause 9.2).
• An in-line comment includes all the text from the initial characters “/*” to the final characters
“*/”, except that “/**” begins a documentation comment rather than a lexical comment (see
below) and “/*@” begins an inline code block (see Subclause 9.2).
• A documentation comment includes all the text from the initial characters “/**” to the final
characters “*/”. The comment text is the text between the initial characters “/**” and the final
characters “*/”.
The first two kinds of comments are together known as lexical comments.
Cross References
1. InputCharacter see Subclause 7.1
2. LineTerminator see Subclause 7.1
Grammar
DocumentationComment
= "/**" CommentText "*/"
Cross References
1. CommentText see Subclause 7.4.1
7.5 Names
The name of a named element denotes the element without reference to the namespace of which it is a
member (if any). A name may contain any character. However, names that have the form of identifiers
may be represented more simply.
Grammar
Name = Identifier
| UnrestrictedName
Identifier
= IdentifierChars but not a ReservedWord or BooleanLiteral
IdentifierChars
= IdentifierLetter { IdentifierLetterOrDigit }
IdentifierLetterOrDigit
= IdentifierLetter
| Digit
IdentifierLetter
= "a" … "z" | "A" … "Z" | "_"
Digit = "0"
| NonzeroDigit
NonzeroDigit = 1 … "9"
UnrestrictedName
= "'" NameCharacter { NameCharacter } "'"
NameCharacter
= InputCharacter but not "'" or "\\"
| EscapeSequence
EscapeSequence
= "\\" EscapedCharacter
EscapedCharacter
= "'" | "\"" | "b" | "f" | "t" | "n" | "\\"
Cross References
1. InputCharacter see Subclause 7.1
Cross References
1. BooleanLiteral See Subclause 7.7.1
2. NaturalLiteral See Subclause 7.7.2
3. UnboundedValueLiteral See Subclause 7.7.3
4. StringLiteral See Subclause 7.7.4
The Alf standard model library PrimitiveTypes package includes the type Natural that is a
specialization of both Integer and UnlimitedNatural (see Subclause 11.2.1), and natural literals are
considered to inherently have this type. However, since UML does not provide any literal specification
metamodel representation for Natural, any time a natural literal is used, it must be possible to
determine from context whether it is an integer or an unlimited natural value that is actually required, so
the proper metamodel representation can be chosen when the literal is mapped to fUML. If this cannot
be determined implicitly, then an explicit cast (see Subclause 8.5.5) to type Integer or type
UnlimitedNatural must be used.
A natural literal may be expressed in decimal (base 10), binary (base 2), octal (base 8) or hexadecimal
(base 16). A decimal literal consists of either the single character “0”, representing the integer 0, or a
digit from “1” to “9” optionally followed by one or more digits from “0” to “9”, representing a positive
integer. A binary literal consists of the prefix “0b” or “0B” followed by one or more of the binary digits
“0” or “1”. A hexadecimal literal consists of the prefix “0x” or “0X” followed by one or more
hexadecimal digits. Hexadecimal digits with values 10 through 15 are represented by the letters “a”
through “f” or “A” through “F”, respectively (case is not significant). An octal literal consists of the digit
“0” followed by one or more digits from “0” to “7”. Underscores may be inserted between digits but are
ignored in determining the value of the literal.
Subclause 9.1 of the fUML Specification allows a conforming implementation to limit the supported
values for Integer and UnlimitedNatural types to a finite set. An Alf implementation may also adopt
such a limitation, in which case it may reject any natural literal representing a value outside the
supported set.
Examples
1234
0
0b1010111000010000
0B0100_1010_0101_1011
0xAE10
0X4a_5b
057410
0_045_133
Grammar
NaturalLiteral
= DecimalLiteral
| BinaryLiteral
| HexLiteral
| OctalLiteral
DecimalLiteral
= "0"
| NonzeroDigit { [ "_" ] Digit }
Cross References
1. NonzeroDigit see Subclause 7.5
2. Digit see Subclause 7.5
Cross References
1. InputCharacter see Subclause 7.2
2. EscapeSequence see Subclause 7.5
7.8 Punctuation
The tokens below are considered to be punctuation.
NOTE. Some tokens below are made up of two symbols that may themselves individually be tokens.
Nevertheless, the two-symbol token is not considered a combination of the individual symbol tokens.
For example, “::” is considered a single token, not a combination of two “:” tokens. Input characters
are grouped from left to right to form the longest possible sequence of characters to be grouped into a
single token. Thus “a:::b” would analyzed into four tokens: “a”, “::”, “:” and “b”.
Grammar
Punctuation
= "(" | ")" | "{" | "}" | "[" | "]" | ";" | "," | "." | ":"
| ".." | "::" | "=>" | "->"
7.9 Operators
The tokens below are considered to be operators.
Grammar
Operator
= "=" | ">" | "<" | "!" | "~" | "?" | "@" | "$"
| "==" | "<=" | ">=" | "!=" | "&&" | "||" | "++" | "--"
| "+" | "-" | "*" | "/" | "&" | "|" | "^" | "%"
| "+=" | "-=" | "*=" | "/=" | "&=" | "|=" | "^=" | "%="
| "<<" | ">>" | ">>>" | "<<=" | ">>=" | ">>>="
8.1 Overview
This subclause describes the top-level syntax and semantics for expressions. The next level
categorization of expressions syntactically is into conditional-test expressions (see Subclause 8.7) and
assignment expressions (see Subclause 8.8). However, in the subclauses following this subclause,
expressions are described in a traditional “bottom up” fashion, starting with the simplest forms of
expressions and working back up to conditional-test and assignment expressions.
Syntax
Expression(e: Expression)
= ConditionalExpression(e)
| AssignmentExpression(e)
Syntax
TypeName(q: QualifiedName)
= QualifiedName(q)
| "any"
QualifiedName(q: QualifedName)
= ColonQualifiedName(q)
| DotQualifiedName(q)
| UnqualifiedName(q)
PotentiallyAmbiguousQualifiedName(q: QualifedName)
= ColonQualifiedName(q)
| DotQualifiedName(q) (q.isAmbiguous=true)
| UnqualifiedName(q)
ColonQualifiedName(q: QualifiedName)
= NameBinding(q.nameBinding) "::" { NameBinding(q.nameBinding) "::" }
NameBinding(q.nameBinding)
DotQualifiedName(q: QualifiedName)
= NameBinding(q.nameBinding)) "." { NameBinding(q.nameBinding) "." }
NameBinding(q.nameBinding)
UnqualifiedName(q: QualifiedName)
= NameBinding(q.nameBinding)
NameBinding(n: NameBinding)
= Name(n.name) [ TemplateBinding(n.binding) ]
TemplateBinding(b: TemplateBinding)
= PositionalTemplateBinding(b)
| NamedTemplateBinding(b)
NOTE. Named template binding notation is not available at the minimum conformance level (see
Subclause 2.1).
NOTE. The space between the right angle brackets at the end of the last example above are necessary in
order for it to parse correctly. If there was no space, then the symbol “>>” would be recognized as a
right shift operator, not two angle brackets (see Subclause 7.8 on the lexical analysis of multi-character
symbols).
The standard library class Map has two template parameters, K and V. The following are all equivalent
bindings for this template.
Map<String, Definition>
Map<K=>String, V=>Definition>
Map<V=>Definition, K=>String>
Cross References
1. Literal Expression see Subclause 8.3.2
2. NameExprssion see Subclause 8.3.3
3. ThisExpression see Subclause 8.3.4
4. ParenthesizedExpression see Subclause 8.3.5
5. PropertyAccessExpression see Subclause 8.3.6
6. InvocationExpression see Subclause 8.3.7
7. InstanceCreationExpression see Subclause 8.3.12
8. LinkOperationExpression see Subclause 8.3.13
9. ClassExtentExpression see Subclause 8.3.14
10. SequenceConstructionExpression see Subclause 8.3.15
11. SequenceAccessExpression see Subclause 8.3.16
12. SequenceOperationExpression see Subclause 8.3.17
13. SequenceReductionExpression see Subclause 8.3.18
14. SequenceExpansionExpression see Subclause 8.3.19
Semantics
See the discussion of semantics for each kind of expression in subsequent subclauses.
NOTE. A parenthesized expression has the abstract syntax of its contained expression.
Semantics
A parenthesized expression is evaluated by evaluating the contained expression and results in the values
of the contained expression. The use of parenthesizes only effects order of evaluation, not how the
contained expression is evaluated.
The type and multiplicity of a parenthesized expression are the same as the contained expression.
Concrete Syntax
PropertyAccessExpression(e: PropertyAccessExpression)
= FeatureReference(e.featureReference)
FeatureReference(f: FeatureReference)
= FeatureTargetExpression(f.expression) "." NameBinding(f.nameBinding)
FeatureTargetExpression(e: Expression)
= NameTargetExpression(e)
| NonNamePrimaryExpression(e)
If the association Owns is in the current scope (that is, visible without qualification), and jack is a
Person, then the expression
jack.house
NOTE. It is not an error for the result of the target expression in a property access expression to be
empty. In this case, the property access expression evaluates to an empty sequence.
8.3.8 Tuples
A tuple is a list of expressions used to provide the arguments for an invocation. There are two kinds of
tuples, positional tuples and named tuples. In a positional tuple, the arguments are matched to the
parameters in order, by position. A named tuple, on the other hand, includes an explicit identification of
the name of the parameter corresponding to each argument.
In this case, the argument 1 corresponds to the parameter x and the argument true corresponds to the
parameter y. This is equivalent to the invocation with the named tuple:
A(x=>1, y=>true)
However, with a named tuple, the order of the arguments may be changed:
A(y=>true, x=>1)
Further, since the parameter y is optional (multiplicity lower bound of 0), no argument needs to be
provided for it at all in the named tuple notation. For example, the following invocation using a named
tuple:
A(x=>1)
Assignment
Tuples with arguments corresponding to inout or out parameters act as assignments. The expressions
corresponding to such parameters must have the form of the left hand side of an assignment (see
Subclause 8.8), that is, either a local name or an attribute reference, possibly indexed. The assigned
source for a name after the argument expression is determined as for the left hand side of an assignment,
with the parameter as its assigned expression.
Association Read
Roster::player(team=>t, season=>y)
Roster.player(t,y)
Owns::house(jack)
Syntax
BehaviorInvocationTarget(e: BehaviorInvocationExpression)
= PotentiallyAmbiguousQualifiedName(e.target)
The invocation
including(Integer[]{1,2,3}, 4)
is then equivalent to
including<Integer>(Integer[]{1,2,3}, 4)
Since the literal 4 has type Natural (see Subclause 7.7.2) and the effective common ancestor of
Integer and Natural is Integer (since Integer generalizes Natural—see Subclause 11.2.1). The
result is a sequence of Integer values.
NOTE. The above rule for argument type inference does not attempt to account for behavior parameters
that may have types that are template bindings using the behavior template parameters as arguments (for
example, bindings of collection class with a behavior template parameter as an argument). This greatly
simplifies the inference rule and is adequate in most cases. In particular, the fact that the standard
collection functions in Alf can use the UML notion of multiplicity rather than collection classes in the
typing of parameters reduces the need for a more complicated inference rule in cases involving
sequences and collections.
When a behavior invocation expression is evaluated, the values resulting from the evaluation of each
input argument expression are assigned to the appropiate in and inout parameter and the behavior is
invoked. Once the behavior completes execution, the result values for each inout and out parameter are
assigned to their corresponding output arguments. (Note that these assignments may involve implicit
conversions, as discussed in Subclause 8.8.)
If the named behavior has a return parameter, then the behavior invocation expression evaluates to the
value of that parameter. The type and multiplicity of the behavior invocation expression are the same as
for the return parameter.
If the named behavior does not have a return parameter, then it evaluates to the null (empty) collection.
It is untyped with multiplicity [0..0].
the expression
Roster::player(team=>t, season=>y)
or, equivalently,
Roster.player(t,y)
is equivalent to
jack.house
NOTE. This means that the argument expressions in the tuple for the feature invocation are re-
evaluated for the invocation on each instance in the sequence. It is not an error for the result of the
primary expression in a feature invocation expression to be empty. In this case, no invocations occur and
the tuple is never evaluated.
Syntax
SuperInvocationTarget(e: SuperInvocationExpression)
= "super" [ "." QualifiedName(e.target) ]
Syntax
InstanceCreationExpression(e: InstanceCreationExpression)
= "new" QualifiedName(e.constructor) Tuple(e.tuple)
creates an object of the class Employee and calls the constructor transferred on that object with the
argument employeeInfo.
If the object creation expression names a class, then the constructor called is one with the same name as
the class. Thus, the expression
new Employee(id, name)
is equivalent to
new Employee::Employee(id, name)
If an object creation expression is constructorless, then evaluation of the expression still results in the
creation of a new object of the named class, but no constructor operation is called. However, if any
attributes of the class have default value expressions (see UML Superstructure, Subclause 7.3.44), then
these are evaluated to give the initial values of the corresponding attributes. Such initialization has the
semantics of an assignment of the expression to the attribute (see Subclause 8.8). Attributes are
initialized in the order in which they are defined in the class.
Finally, if the class of the object being created is active, then the classifier behavior for that class is
automatically started once the object is created and after any constructor call completes.
The type of an object creation expression is the class that owns the constructor (which is the named
class, if it is named explicitly) and the multiplicity is [1..1].
Data Value Creation Expression
If the name in an instance creation expression denotes a data type, then the expression creates a data
value. In this case, the tuple is used to specify values for the attributes of the data value. If a named tuple
is used, then the names must correspond to the names of the attributes of the data type. The identified
data type must not be abstract.
Arguments are matched with attributes of the named data type as described in Subclause 8.3.8, with the
attributes being considered as in parameters. Each argument expression must be to the corresponding
attribute (see Subclause 8.8 for the definition of assignability).
For example, consider the data type
datatype Position {
public x: Integer;
All the following data value expressions create equivalent data values of this type:
new Position(1,2)
new Position(x=>1, y=>2)
new Position(y=>2, x=>1)
The type of a data value creation expression is the named data value and the multiplicity is [1..1].
Syntax
LinkOperationExpression(e: LinkOperationExpression)
= QualifiedName(e.associationName) "." LinkOperation(e.operation)
LinkOperationTuple(e.tuple)
LinkOperation(op: String)
= "createLink"(op)
| "destroyLink"(op)
| "clearAssoc"(op)
LinkOperationTuple(t: Tuple)
= PositionalTuple(t)
| IndexedNamedTuple(t)
IndexedNamedTuple(t: NamedTuple)
= "(" IndexedNamedExpression(t.expressions)
{ "," IndexedNamedExpression(t.expressions) } ")"
IndexedNamedExpression(n: NamedExpression)
= Name(n.name) [ Index(n.index) ] "=>" Expression(n.expression)
Index(e: Expression)
= "[" Expression(e) "]"
the expression
Owns.createLink(jack, newHouse)
creates a link with the given end values (note that the order of the arguments corresponds to the order of
the association ends in the association definition). This link can then be destroyed using the expression
Owns.destroyLink(jack, newHouse)
and
Owns.destroyLink(owner=>jack, house=>newHouse)
inserts the newHouse at the beginning of the list of houses for jack. If an index is not given for an
ordered end, then the default is *, which indicates adding at the end.
Finally, there is an additional link operation, clearAssoc, which may only be used with associations. It
destroyes all links of the named association that have at least one end with a given value. Thus, the
expression
Owns.clearAssoc(jack)
Syntax
ClassExtentExpression(e: ClassExtentExpression)
= QualifiedName(e.type) "." "allInstances" "(" ")"
Syntax
SequenceConstructionExpression(e: SequenceConstructionExpression)
= NullExpression
| SequenceElementsExpression(e)
NullExpression
= "null"
SequenceElementsExpression(e: SequenceConstructionExpression)
= [ "new" ] SequenceElementsTypePart(e)
"{" SequenceElements(e.elements) "}"
SequenceElementsTypePart(e: SequenceConstructionExpression)
= TypeName(e.typeName)
[ MultiplicityIndicator (e.hasMultiplicity=true) ]
MultiplicityIndicator
= "[" "]"
SequenceElements(se: SequenceElements)
= SequenceElementList(se)
| SequenceRange(se)
SequenceElementList(sel: SequenceExpressionList)
= [ SequenceElement(sel.element) { "," SequenceElement(sel.element) }
[ ","] ]
SequenceElement(e: Expression)
= Expression(e)
| SequenceInitializationExpression(e)
SequenceInitializationExpression(e: SequenceConstructionExpression)
= [ "new" ] "{" SequenceElements(e.elements) "}"
SequenceRange(sr: SequenceRange)
= Expression(sr.rangeLower) ".." Expression(sr.rangeUpper)
When used to construct a collection object, it is possible that the elements of a sequence element list are
themselves collections. In this case, the type parts of the nested sequence construction expressions may
be omitted, since their types may be inferred from the element type of the collection class being
constructed.
For example, the sequence construction expression
List< Set<Integer> >{{1}, {2,3}, {4,5,6}}
is equivalent to
List< Set<Integer> >{Set<Integer>{1}, Set<Integer>{2,3}, Set<Integer>{4,5,6}}
Empty Sequences
The list of element expressions in a sequence construction expression may be empty. However, the static
type of an empty sequence is still as specified in the expression. Thus, Integer[]{} is an empty
sequence of integers while String[]{} is an empty sequence of strings. An empty sequence has
multiplicity [0..0].
The keyword null is equivalent to any[]{}, that is, an untyped empty sequence.
Syntax
SequenceAccessExpression(e: SequenceAccessExpression)
= PrimaryExpression(e.primary) Index(e.index)
the sequence access expression a[3] evaluates to 30. Note that indexing is from 1.
Syntax
SequenceOperationExpression(e: SequenceOperationExpression)
= ExtentOrExpression(e.primary) "->" QualifiedName(e.operation)
Tuple(e.tuple)
ExtentOrExpression(e: ExtentOrExpression)
= QualifiedName(e.name)
| NonNamePrimaryExpression(e.nonNameExpression)
is equivalent to the following behavior invocation expression for the library behavior including:
including(a,x)
Both of these expression evaluate to a sequence with all the elements of a and the additional element x
at the end.
By contrast, suppose that a is a sequence of objects of the same class, which has an operation called
including. Then, the operation call
a.including(x)
is equivalent to
add(a,2)
Clearly, in this case, the target primary expression must have the form of the left hand side of an
assignment (see Subclause 8.8). Note that if the target primary expression is a local name (such as “a” in
the example above), then, by the usual semantics of inout parameters, such an “in place” sequence
operation expression is considered to be a re-assignment of that local name (see Subclause 8.3.8 on
assignments and inout parameters).
Sequence Operations on Collections
The assignability rule for collection conversion (see Subclause 8.8) leads to special behavior in the case
in which the type of the initial primary expression is a collection class (see Subclause 11.6) and its
multiplicity upper bound is no greater than 1 (and as long as the initial parameter is an in parameter). In
this case, the operation toSequence is first called on the collection object resulting from evaluating the
primary expression, and the sequence operation is then performed on the resulting sequence.
For example, suppose customerList has the type List<Customer>. Then the expression
customerList->size()
is equivalent to
size(customerList)
Since the argument type for the CollectionFunctions::size has multiplicity [*], this is equivalent to
size(customerList.toSequence())
which gives the number of elements in the collection. Note that this gives the same result as a regular
call on the size operation provided by a collection object:
customerList.size()
is equivalent to
Customer.allInstances()->size()
or
size(Customer.allInstances())
which all evaluate to the number of objects currently in the extent of the Customer class (where
Customer.allInstances() is a class extent expression—see Subclause 8.3.14).
Syntax
ReductionExpression(e: ReductionExpression)
= ExtentOrExpression(e.primary) "->" "reduce"
[ "ordered" (e.isOrdered=true) ] QualifiedName(e.behavior)
evaluates to 6—the same as 1+2+3 (see also Subclause 8.3.15 on the sequence construction expression
notation used in the primary expression above).
Normally, the order in which the behavior of a sequence reduction expression is applied to pairs of
values is indeterminate. This will not affect the result of the expression if the behavior is commutative
and associative. For example, in the above example using addition may be evaluated as 1+2+3 or 1+3+2
or 2+3+1, or in any other order, and the result is always 6.
However, if the reducing behavior is not commutative and associative, or has side effects, then the order
in which elements are selected from the sequence will affect the result of the expression. In this case, an
ordered reduction may be used by adding the keyword “ordered”, so the reducing behavior will be
applied to adjacent pairs according to the collection order. The result of each invocation of the behavior
replaces the two values taken as input at the same position in the order as the original two values.
For example, matrix multiplication is not commutative. The expression
Matrix[]{A, B, C} -> reduce ordered MatMult
is equivalent to
vector.toSequence() -> reduce '+'
Also as for sequence operation expressions (see Subclause 8.3.17), sequence reduction expressions
allow the special notation in which a class name is used as a shorthand for a class extent expression.
“select” is the expansion operation name and “x” is the expansion variable name.
An expansion variable may not be reassigned within the argument expression of a sequence expansion
expression, and it is considered unassigned after the sequence expansion expression. Further, while the
argument expression may reference local names defined outside that expression, it may not reassign
such local names. New local names may be defined and referenced within the argument expression, but
all such names are considered unassigned after the sequence expansion expression.
NOTE. The above rule is necessary, since, if the sequence being expanded is empty, the argument
expression will never be evaluated and names assigned within it would have no value on their assigned
source. The rule also allows sequence expansion expressions to be mapped to expansion regions, which
are not allowed to have outgoing flows or output pins in fUML (see fUML Specification, Subclause
7.4.4.2.2).
Even though a sequence expansion expression is not equivalent to a behavior invocation, a collection
object may be directly acted on in such an expression analogously to how it may be acted on in a
sequence operation expression (see Subclause 8.3.17). The operation toSequence is called on the
collection object, and the expansion is applied to the result of that operation.
For example, if customerList has the type List<Customer>, then the sequence expansion expression
customerList->select c (c.name == customerName)
is equivalent to
Customer.toSequence()->select c (c.name == customerName)
is equivalent to
Customer.allInstances()->select c (c.name == customerName)
Syntax
SelectOrRejectOperation(e: SelectOrRejectExpression)
= "select"(e.operation)
| "reject"(e.operation)
The reject operation is similar to select, except that elements for which the argument expression
evaluates to false are included in the result sequence. The reject operation is thus equivalent to a
select operation with the argument expression negated.
For example, the following expression selects all employees who are not married:
employees->reject e (e.isMarried)
Examples
employees->collect e (e.birthDate)
processSteps->iterate step (step.execute())
Syntax
CollectOrIterateOperation(e: CollectOrIterateExpression)
= "collect"(e.operation)
| "iterate"(e.operation)
An iterate operation has the same behavior as a collect operation, except that the argument
expression is evaluated sequentially for all elements of the input sequence, in order, rather than
concurrently, as is the case for collect. This can be useful when the argument expression potentially
has side effects.
For example, in the evaluation of the expression
processSteps->iterate step (step.execute())
the execution of the process steps will occur sequentially, and the execution of each step will take place
in the context resulting from the completion of the previous step. As for collect, any results returned
from the execute operation invocations will be collected into a result sequence.
Syntax
ForAllOrExistsOrOneOperation(e: ForAllOrExistsOrOneExpression)
= "forAll"(e.operation)
| "exists"(e.operation)
| "one"(e.operation)
Figure 8-23 Abstract Syntax for forAll, exists and one Expressions
Cross References
1. SequenceExpansionExpression see Subclause 8.3.19
The result of an exists operation is true if the argument expression evaluates to true for at least one
element of the input sequence.
For example, the following expression evaluates to true if at least one employee has the first name
"Jack":
employees->exists e (e.firstName=="Jack")
The result of a one operation is true if the argument expression evaluates to true for exactly one element
of the input sequence.
For example, the following expression evaluates to true if there is exactly one employee with the title
"President":
employees->one e (e.title=="President")
Syntax
IsUniqueOperation(e: IsUniqueExpression)
= "isUnique"(e.operation)
Prefix Form
++count
--numberWaiting[queueIndex]
Syntax
IncrementOrDecrementExpression(e: IncrementOrDecrementExpression)
= PostfixExpression(e)
| PrefixExpression(e) (e.isPrefix=true)
PostfixExpression(e: IncrementOrDecrementExpression)
= LeftHandSide(e.operand) AffixOperator(e.operator)
PrefixExpression(e: IncrementOrDecrementExpression)
= AffixOperator(e.operator) LeftHandSide(e.operand)
AffixOperator(op: String)
= "++"(op) | "--"(op)
Syntax
BooleanUnaryExpression(e: BooleanUnaryExpression)
= "!"(e.operator) UnaryExpression(e.operand)
Syntax
BitStringUnaryExpression(e: BitStringUnaryExpression)
= "~"(e.operator) UnaryExpression(e.operand)
The functionality of the BitString bit-wise complement operator is the same as an application of the
Alf library BitStringFunctions::'~' function (see Subclause 11.3.5) with the operand expression as
its argument. The result is a bit string that has a bit set (value 1) in each bit position in which the
operand bit string had its bit unset (value 0) and a bit unset (value 0) in each bit position in which the
operand bit string had its bit set (value 1).
Syntax
NumericUnaryExpression(e: NumericUnaryExpression)
= NumericUnaryOperator(e.operator) UnaryExpression(e.operand)
NumericUnaryOperator(op: String)
= "+"(op) | "-"(op)
NOTE. While the unary plus operator does not have any mathematical effect on its operand, it can be
used as a way to effectively denote an Integer literal value. For example the literal “1234” has the type
Syntax
CastExpression(e: CastExpression)
= "(" TypeName(e.typeName) ")" NonNumericUnaryExpression(e.operand)
NonNumericUnaryExpression(e: Expression)
= PrimaryExpression(e)
| PostfixExpression(e)
| BooleanUnaryExpression(e)
| BitStringUnaryExpression(e)
| CastExpression(e)
| IsolationExpression(e)
evaluates to
Integer[]{1,2}
NOTE. The library type Natural is a subtype of Integer and UnlimitedNatural. This means that
natural literals of type Natural (see Subclause 7.7.2) can be cast to Integer or UnlimitedNatural.
Thus, (Integer)2 is the Integer value 2, while (UnlimitedNatural)2 is the UnlimitedNatural
value 2.
The multiplicity lower bound of a cast expression is 0 and the upper bound is the same as that of the
operand expression.
Syntax
IsolationExpression(e: IsolationExpression)
= "$"(e.operator) UnaryExpression(e.operand)
Syntax
UnaryOrMultiplicativeExpression(e: Expression)
= UnaryExpression(e)
| MultiplicativeExpression(e)
MultiplicativeExpression(e: ArithmeticExpression)
= UnaryOrMultiplicativeExpression(e.operand1)
MultiplicativeOperator(e.operator) UnaryExpression(e.operand2)
MultiplicativeOperator(op: String)
= "*"(op) | "/"(op) | "%"(op)
UnaryOrArithmeticExpression(e: Expression)
= UnaryOrMultiplicativeExpression(e)
| AdditiveExpression(e)
AdditiveExpression(e: ArithmeticExpression)
= UnaryOrArithmeticExpression(e.operand1)
AdditiveOperator(e.operator)
UnaryOrMultiplicativeExpression(e.operand2)
AdditiveOperator(op: String)
= "+"(op) | "-"(op)
Syntax
ArithmaticOrShiftExpression(e: Expression)
= UnaryOrArithmeticExpression(e)
| ShiftExpression(e)
ShiftExpression(e: ShiftExpression)
= ArithmeticOrShiftExpression(e.operand1) ShiftOperator(e.operator)
UnaryOrArithmeticExpression(e.operand2)
ShiftOperator(op: String)
= "<<"(op) | ">>"(op) | ">>>"(op)
NOTE. The restriction on associative relational expressions avoids a syntactic ambiguity with the
syntax for the invocation of a template behavior with an explicit binding. For example, the expression
A<B>(C) can be unambiguously parsed as an invocation of the behavior A<B>, since the “>” cannot
legally be parsed as a relational greater than operator.
Examples
sensorReading > threshold
size < maxSize
size >= minSize
count <= limit
The relational operators are used to compare the values of two numbers. The number being compared
may be either integers or unlimited naturals, but it is not legal to directly compare an integer to an
unlimited natural number.
Thus, the expression
3 < *
is legal (and evaluates to true), since the natural literal 3 is automatically cast to UnlimitedNatural in
this context. However, the expression
+3 < *
is not legal, because the literal +3 has type Integer. A cast expression (see Subclause 8.5.5) must be
used in order to directly compare an integer value to an unlimited natural value; for example,
(UnlimitedNatural)(+3) < *
evaluates to true.
The functionality of the relational operators is equivalent to the application of the similarly named
primitive functions from the library IntegerFunctions package (see Subclause 11.3.2) or
UnlimitedFunctions package (see Subclause 11.3.4), depending on the type of the operand
expressions, with the two operand expressions as arguments.
Syntax
RelationalOrClassificationExpression(e: Expression)
= ArithmeticOrRelationalExpression (e)
| ClassificationExpression(e)
ClassificationExpression(e: ClassificationExpression)
= ArithmeticOrRelationalExpression(e.operand)
ClassificationOperator(e.operator)
QualifiedName(e.typeName)
ClassificationOperator(op: String)
= "instanceof"(op) | "hastype"(op)
Syntax
ClassificationOrEqualityExpression(e: Expression)
= RelationalOrClassificationExpression(e)
| EqualityExpression(e)
EqualityExpression(e: BinaryExpression)
= ClassificationOrEqualityExpression(e.operand1)
EqualityOperator(e.operator)
RelationalOrClassificationExpression(e.operand2)
EqualityOperator(op: String)
= "=="(op) | "!="(op)
EqualityOrAndExpression(e: Expression)
= ClassificationOrEqualityExpression(e)
| AndExpression(e)
• For &, the result value is true if both argument values are true; otherwise, the result is false.
• For ^, the result value is true if the argument values are different; otherwise, the result is false.
Syntax
InclusiveOrOrConditionalAndExpression(e: Expression)
= ExclusiveOrOrInclusiveOrExpression(e)
| ConditionalAndExpression(e)
ConditionalAndExpression(e: ConditionalLogicalExpression)
= InclusiveOrOrConditionalAndExpression(e.operand1) "&&"(e.operator)
ExclusiveOrOrInclusiveOrExpression(e.operand2)
ConditionalAndOrConditionalOrExpression(e: Expression)
= InclusiveOrOrConditionalAndExpression(e)
| ConditionalOrExpression(e)
ConditionalOrExpression(e: ConditionalLogicalExpression)
= ConditionalAndOrConditionalOrExpression(e.operand1) "||"(e.operator)
InclusiveOrOrConditionalAndExpression(e.operand2)
Syntax
ConditionalExpression(e: Expression)
= ConditionalAndOrConditionalOrExpression(e)
| ConditionalTestExpression(e)
Syntax
AssignmentExpression(e: AssignmentExpression)
= LeftHandSide(e.leftHandSide) AssignmentOperator(e.operator)
Expression(e.rightHandSide)
LeftHandSide(lhs: LeftHandSide)
= NameLeftHandSide(lhs) [ Index(lhs.index) ]
| FeatureLeftHandSide(lhs) [ Index(lhs.index) ]
NameLeftHandSide(lhs: NameLeftHandSide)
= PotentiallyAmbiguousQualifiedName(lhs.target)
FeatureLeftHandSide(lhs: FeatureLeftHandSide)
= FeatureReference(lhs.feature)
AssignmentOperator(op: String)
= "="(op) | "+="(op) | "-="(op) | "*="(op) | "%="(op) | "/="(op) |
"&="(op) | "|="(op) | "^="(op) | "<<="(op) | ">>="(op) | ">>>="(op)
3. Collection Conversion. The type of the right-hand side is a collection class (see Subclause 11.6), the
right-hand side has a multiplicity upper bound of 1 and the type and multiplicity of the result of
applying the toSequence operation to the right-hand side would be assignable to the left-hand side.
The assigned value is the result of implicitly calling the toSequence operation on the result of
evaluating the right-hand side expression.
4. Bit String Converstion. The type of the right-hand side conforms to Integer, and the type of the
left-hand side is BitString. If the multiplicity upper bound of the left-hand side is less than or equal
to 1, then the multiplicity upper bound of the right-hand side cannot be greater than that of the left-
hand side. The assigned value is the result of implicitly invocating the standard library
BitStringFunctions::toInteger function (see Subclause 11.3.5) on each of the values in the
result of evaluating the right-hand side expression. Note that both collection conversion and bit
string conversion may apply. In this case, bit string conversion is applied after collection conversion.
The concept of assignability is defined here for assignments, but it can actually be applied between any
two typed elements with multiplicity. It is used in this way to define the required compatibility between
The result value of an assignment expression is the value of the right-hand side. Thus, the expression
WriteLine(a = 3)
assigns 3 to a and then writes the value “3”. Note that this should not be confused with the named tuple
notation, such as
WriteLine(value => 3)
9.1 Overview
A statement sequence is an Alf text consisting of a list of statements juxtaposed in a linear order. Such
statement sequences may be attached to UML models in order to specify behaviors. A block is a
delineation of a statement sequence for use as a component of a larger syntactic construct.
Examples
{
'activity' = (Activity)(this.types[1]);
group = new ActivityNodeActivationGroup();
group.activityExecution = this;
this.activationGroup = group;
group.activation('activity'.node, 'activity'.edge);
}
Syntax
Block(b: Block)
= "{" StatementSequence(b) "}"
StatementSequence(b: Block)
= { DocumentedStatement(b.statement) }
DocumentedStatement(s: Statement)
= [ DocumentationComment(s.documentation) ] Statement(s)
Statement(s: Statement)
= AnnotatedStatement(s)
| InLineStatement(s)
| BlockStatement(s)
| EmptyStatement(s)
| LocalNameDeclarationStatement(s)
| ExpressionStatement(s)
| IfStatement(s)
| SwitchStatement(s)
| WhileStatement(s)
| DoStatement(s)
| ForStatement(s)
| BreakStatement(s)
| ReturnStatement(s)
| AcceptStatement(s)
| ClassifyStatement(s)
Syntax
AnnotatedStatement(s: Statement)
= "//@" Annotation(s.annotation) { "@" Annotation(s.annotation) }
[ "//" { InputCharacter } ] LineTerminator
Statement(s)
Since the syntax allows an annotated statement to itself be annotated, annotations may be spread across
multiple lines preceding a single “base” statement. For the purposes of determining applicability, per
Table 9-6, of a further annotation of an annotated statement, the annotated statement is to be considered
to be of the same kind as its base statement. However, no annotation may be applied more than once to
the same base statement.
Arguments
The syntax for annotations allows for an optional list of names to be given as arguments of the
annotation. Currently, only the @parallel annotation on a for statement allows such argument (see
Subclause 9.12 for rules related to names used as such arguments).
Isolation
The annotation @isolated may be used with any statement other than the empty or break statements,
indicating that the statement is executed in isolation. That is, during the execution of the statement, no
object accessed as part of the execution of the statement or as the result of a synchronous invocation
from the statement may be modified by any action that is not executed as part of the statement or as the
result of a synchronous invocation from the statement.
The semantics of isolation is discussed in Subclause 8.6.4.1 of the fUML specification.
NOTE. The unary operator $ can also be used to denote isolation at the expression level (see Subclause
8.5.6).
Other annotations are discussed with the description of the statements to which they apply.
Example
/*@inline('C++') // Native code
*data = this;
controller->initiate();
*/
Syntax
InLineStatement(s: InLineStatement)
= InLineHeader(s) CommentText(s.code) "*/"
InLineHeader(s: InLineStatement)
= "/*@" "inline" "(" Name(s.language) ")"
[ "//" { InputCharacter } ] LineTerminator
The example below represents the activity graph shown in Figure 9-45.
//@parallel
{
'activity' = (Activity)(this.types[1]); // Segment 1
{ // Segment 2
group = new ActivityNodeActivationGroup();
group.activityExecution = this;
}
{ // Segment 3
this.activationGroup = group;
group.activation('activity'.node, 'activity'.edge);
}
}
the invocations of the behaviors F and G will execute concurrently with no dependencies between them.
The block as a whole completes execution only after both invocations are complete.
However, there may be data dependencies between the statements in a parallel block. For example, the
statements in the block
//@parallel
{
a = F(1);
b = G(a);
}
will execute sequentially, despite the @parallel annotation, because the invocation of G cannot proceed
until a value is available for a.
In order to prevent data conflicts, it is illegal to assign the same name in more than one statement in a
parallel block. Thus, the block
//@parallel
{
a = 1;
a = F(a); // Illegal!
b = G(2);
}
is illegal, since the name a is reassigned in the second statement. However, the following block is legal:
//@parallel
{
{
a = 1;
a = F(a); // Legal
}
b = G(2);
}
This is because the block now consists of just two statements, the first of which happens to be a
(sequential) block statement. Only the first of these actually assigns a value to the name a. The value of
a after the first statement in the parallel block, and hence after the parallel block as a whole, is the value
given to it (sequentially) by the second assignment.
In the second form, the type name precedes the local name:
CurrencyAmount interest = this.principal * this.rate * period;
The two forms are completely equivalent. In both cases, the local name is assigned the result of
evaluating the expression.
NOTE. The first form of local name declaration is consistent with the usual UML notation for declaring
the type of a name. The second form is consistent with the form of declarations in many common
programming languages and also emphasizes the essential semantics of the statement as an assignment
with an added type constraint.
Examples
let currentOffer : Offer = this.offers[1];
let origin : Point = new(0,0);
CurrencyAmount interest = this.principal * this.rate * period;
let inactiveMembers : Member[] = members -> select member (!member.active);
RealProperty[] realProperties = (RealProperty)assets;
IntegerList list = {1, 2, 3};
Set<RealProperty> fixedAssets = new { land, home, condominium };
Syntax
LocalNameDeclarationStatement(s: LocalNameDeclarationStatement)
= NameDeclaration(s) "=" InitializationExpression(s.expression) ";"
InitializationExpression(e: Expression)
= Expression(e)
| SequenceInitializationExpression(e)
| InstanceInitializationExpression(e)
presuming that Car and Truck are both subclasses of Vehicle. However, the following would not be
legal:
v = new Car();
v = new Truck(); // Type error!
because the initial assignment would determine the type of v as being Car, which is not compatible with
Truck.
A similar effect to the legal assignment above can be achieved using a type cast (see Subclause 8.5.5):
v = (Vehicle)new Car();
v = new Truck(); // Legal
Even though the initial value assigned to v here is a Car, the type of the expression “(Vehicle)new
Car()” is Vehicle, due to the cast. Therefore, the initial assignment determines the type of v as being
Vehicle, so the second assignment is legal.
However, there is an important semantic difference. Type casts in Alf filter values that cannot be cast, so
that
v = (Vehicle)new House();
is legal and will assign null to v. On the other hand, the following is not legal:
let v: Vehicle = new House(); // Type error!
since the class House does not statically conform to the declared type Vehicle.
Initialization Expressions
Since a local name declaration statement already includes an explicit declaration of the type of a new
name, it is possible to use simplified forms for sequence construction expressions (see Subclause 8.3.15)
and instance creation expressions (see Subclause 8.3.12) used as initialization expressions in local name
declaration statements. In these simplified forms, the explicit type part usually included in the
expressions may be omitted, with the type declared as part of the statement being used instead.
For example, in the statement
let fixedAssets: RealProperty[] = { land, home, condominium };
the type part normally required for a sequence construction expression has been omitted. The statement
is equivalent to one in which the type part for the sequence construction expression is the same as the
type declared for the new local name:
let fixedAssets: RealProperty[] = RealProperty[]{ land, home, condominium };
This simplified form may also be used when initializing collection objects. Thus, the statement
let fixedAssets: Set<RealProperty> = { land, home, condominium };
is equivalent to
the explicit constructor description has been omitted from the instance creation expression, leaving only
the keyword new and the tuple. The statement is equivalent to one in which the instance creation
expression is explicitly for the type declared for the new local name:
let origin : Point = new Point(0,0);
NOTE. The initialization expression short hands can also be used in Alf expressions representing
default values, either as integrated with a non-Alf representation of a property or parameter (see
Subclause 8.1) or as the initializer for the definition of an attribute in Alf (see Subclause 10.5.2).
Syntax
ExpressionStatement(s: ExpressionStatement)
= Expression(s.expression) ";"
9.8 if Statements
An if statement allows for the conditional execution of one of a set of blocks of statements. The
conditional blocks are organized into sequential sets of concurrent clauses. Each clause in a concurrent
set includes a conditional expression (which must be of type Boolean) and a block to execute if that
condition is true. An if statement may also optionally have a final clause with a block to execute if no
other conditions are true.
NOTE. The notation for concurrent clauses is not available at the minimum conformance level (see
Subclause 2.1).
Examples
if (reading > threshold) {
monitor.raiseAlarm(sensorId);
}
//@determined @assured
if (reading <= safeLimit) {
condition = normal; }
or if (reading > safeLimit && reading <= criticalLimit) {
condition = alert; }
or if (reading > criticalLimit) {
condition = critical; }
Syntax
IfStatement(s: IfStatement
= "if" SequentialClauses(s) [ FinalClause(s.finalClause) ]
SequentialClauses(s: IfStatement)
= ConcurrentClauses(s.nonFinalClauses)
{ "else" "if" ConcurrentClauses(s.nonFinalClauses) }
ConcurrentClauses(c: ConcurrentClauses)
= NonFinalClause(c.clause) { "or" "if" NonFinalClause(c.clause) }
NonFinalClause(c: NonFinalClause)
= "(" Expression(c.expression) ")" Block(c.block)
FinalClause(b: Block)
= "else" Block(b)
the invocation is executed only if the condition reading > threshold is true. A final clause may be
added, as in
if (reading > threshold) {
monitor.raiseAlarm(sensorId);
}
else {
In this case, the logReading operation is called if reading > threshold is false.
An if statement may also have a list of conditional clauses that are tested sequentially. For example,
if (reading <= safeLimit) {
condition = normal;
}
else if (reading <= criticalLimit) {
condition = alert;
}
else {
condition = critical;
}
Concurrent Clauses
Clauses beginning with or instead of else are tested concurrently rather than sequentially. For example,
if (reading <= safeLimit) {
condition = normal;
}
or if (reading > safeLimit && reading <= criticalLimit) {
condition = alert;
}
or if (reading > criticalLimit) {
condition = critical;
}
Note that the second condition has the added test reading > safeLimit, since the first condition will
no longer be evaluated sequentially before the second. If this addition had not been made, then, if, in
fact, reading <= safeLimit was true, both of the first two conditions could be true, and either of the
associated blocks might actually execute (but only one would).
Sequential and conditional clauses can also be mixed, but sets of contiguous concurrent clauses are
always sequenced together. Thus, in
if (reading <= safeLimit) {
condition = normal; }
else if (reading > safeLimit && reading <= criticalLimit} {
condition = alert; }
or if (reading > criticalLimit && reading < errorLimit) {
condition = critical; }
else {
condition = error; }
if the first condition is false, then both the next two conditions are evaluated concurrently. If both these
conditions are also false, then the final clause is executed.
Annotations
The annotations @assured and @determined may be used with an if statement (see also Subclause 9.2
on annotations). The annotation @assured indicates that at least one condition in the if statement will
always evaluate to true. The annotation @determined indicates that at most one condition will evaluate
to true. The annotations may be used together, which indicates that exactly one condition will always
evaluate to true.
Syntax
SwitchStatement(s: SwitchStatement)
= "switch" "(" Expression(s.expression) ")"
"{" { SwitchClause(s.nonDefaultClause) }
[ SwitchDefaultClause(s.defaultClause) ] "}"
SwitchClause(s: SwitchClause)
= SwitchCase(s.case) { SwitchCase(s.case) }
NonEmptyStatementSequence(s.block)
SwitchCase(e: Expression)
= "case" Expression(e) ":"
Syntax
WhileStatement(s: WhileStatement)
= "while" "(" Expression(s.condition) ")" Block(s.body)
Names
Local names defined within the condition expression of a while statement are available within the body
block of the while statement, with the value as computed on each iteration of the loop. They are also
available after completion of execution of the while statement, with the values assigned as of the last
evaluation of the while condition expression.
Local names within the body block of a while statement may be used within that block, but they are
prohibited from being used outside the block. This is because they could be uninitialized if the while
statement does not execute its body.
Local names defined before a while statement may be reassigned within the while statement. After
completion of execution of the while statement, they have the values assigned as of the last evaluation
of the while statement.
9.11 do Statements
The do statement executes a block and an expression repeatedly until the value of the expression is false.
The expression must have type Boolean and a multiplicity upper bound of 1.
Examples
do {
line = file.readNext();
WriteLine(line);
} while (line != endMarker);
Syntax
DoStatement(s: DoStatement)
= "do" Block(s.body) "while" "(" Expression(s.condition) ")" ";"
//@parallel
for (ActivityEdgeInstance outgoingEdge: this.outgoingEdges) {
outgoingEdge.sendOffer(tokens);
}
// Fast Fourier Transformation computation
//@parallel(Sn_Even,Sn_Odd)
for (lower in S_Lower, upper in S_Upper, root in V) {
//@parallel
{
Sn_Even -> add(lower+upper);
Sn_Odd -> add((lower-upper)*root);
}
}
Syntax
ForStatement(s: ForStatement)
= "for" "(" ForControl(s) ")" Block(s.body)
ForControl(s: ForStatement)
= LoopVariableDefinition(s.variableDefinition)
{ "," LoopVariableDefinition(s.variableDefinition) }
LoopVariableDefinition(v: LoopVariableDefinition)
= Name(v.variable) "in" Expression(v.expression1)
[ ".." Expression(v.expression2) ]
| TypeName(v.typeName) Name(v.variable) ":"
Expression(v.expression1) (typeIsInferred=false)
The loop variable member is then implicitly given the type Member, the same type as that of the name
expression memberList.
However, collection conversion may be performed on the expression in a loop variable definition. That
is, if the type of the expression is a collection class (see Subclause 11.6) and the multiplicity upper
bound of the expression is no greater than 1, then the operation toSequence is implicity called on the
expression to produce the sequence of values for the loop variable. The loop variable is then the type of
In this form, the declared type of the loop variable normally must conform to the type of the expression
(see Section 8.2 for the definition of type conformance). However, if collection conversion applies to the
expression, then the declared type must conform to the element type of the collection.
NOTE. The second form of loop variable definition has a similar syntax to that used in a “for each”
statement in Java.
A loop variable definition of the form var in expr1..expr2 is a shorthand for var in Integer[]
{expr1..expr2} (see Subclause 8.3.15 on ranges in sequence construction expressions). In this case,
both expressions must have type Integer and a multiplicity upper bound of 1. A loop variable so
defined takes on sequential integer values in each loop iteration, beginning with the value given by
expr1 and ending with the value given by expr2. If the second value is less than the first, then the for
loop execution completes with no iterations.
Iterative Execution
When a for statement is executed, the expressions in its loop variable definitions are evaluated
concurrently. If the result for the first variable is a sequence of at least one value, and the for statement
has no while condition expression, then the block of the for statement is executed once for each value
in the sequence. On each such execution, the local names of the loop variables within the block have
corresponding values from the sequences resulting from the evaluation of the expressions in their
definitions.
Note that the sequences for all the loop variables in a specific execution of a for statement should have
the same size. However, if this is not true, it is the sequence for the first variable that controls the
execution. If another variable has a sequence of a larger size than the first variable, then the additional
values will be ignored. If it has a sequence of a smaller size, then the variable will be empty on iterations
after all values in its sequence have been used. For this reason, the first loop variable has the multiplicity
[1..1], while any other loop variables are given the multiplicity [0..1].
NOTE. At the minimum conformance level (see Subclause 2.1), a for statement is allowed to have only
one loop variable.
By default, the executions of the body block of a for statement occur in sequential iterations. Values are
taken from the sequence for each loop variable in order.
Since a loop variable expression is only evaluated once, any local names defined in it have the values
assigned during that evaluation for all executions of the body block of the for statement, unless
reassigned within that block.
Local names defined within the body block of a for statement are prohibited from being accessed
outside the for statement, since they could be uninitialized if the for statement does not execute its
For example, consider the following piece of a Fast Fourier Transform (FFT) computation, using an
iterative for statement.
Sn_Even = Integer[]{};
Sn_Odd = Integer[]{};
This is computationally correct, but it forces sequential execution of what is essentially a parallel
algorithm. This can be corrected by inserting appropriate @parallel annotations:
Sn_Even = Integer[]{};
Sn_Odd = Integer[]{};
//@parallel(Sn_Even,Sn_Odd)
for (lower in S_Lower, upper in S_Upper, root in V) {
//@parallel
{
Sn_Even -> add(lower+upper);
Sn_Odd -> add((lower-upper)*root);
}
}
The listing of the names Sn_Even and Sn_Odd in the @parallel annotation is required so that the add
operation invocations continue to be permitted within the for statement.
NOTE. The normal behavior invocation notation (see Subclause 8.3.9) may also be used for the add
function instead of the sequence operation notation (see Subclause 8.3.17). For example “Sn_Even-
>add(lower+upper);” may instead be written “add(Sn_Even, lower+upper);”. The behavior
invocation notation is available at the minimum conformance level, while the sequence operation
notation is not available until the full conformance level (see also Subclause 2.1 on syntactic
conformance levels).
If, after the loop variable definitions of a parallel for statement, a name has an assigned source, then it
must have the same assigned source after the block of the for statement. Other than for names defined in
the @parallel annotation of the for statement, the assigned source for such names is the same after the
Syntax
ReturnStatement(s: ReturnStatement)
= "return" Expression(s.expression) ";"
Syntax
AcceptStatement(s: AcceptStatement)
= SimpleAcceptStatement(s)
| CompoundAcceptStatement(s)
SimpleAcceptStatement(s: AcceptStatement)
= AcceptClause(s.acceptBlock) ";"
CompoundAcceptStatement(s: AcceptStatement)
= AcceptBlock(s.acceptBlock) { "or" AcceptBlock(s.acceptBlock) }
When this statement is executed, the thread of execution it is on is suspended, waiting for the receipt of
an instance of the signal SignalNewArrival. When such a receipt later triggers the accept statement, it
completes its execution, and further execution on its thread can continue.
An accept statement can also optionally include the definition of a local name that is used to hold an
accepted signal instance:
accept (arrival: SignalNewArrival);
WriteLine(arrival.name);
A local name so defined has the signal as its type. It must be unassigned before the accept statement.
A single accept statement can list multiple signals, any one of which may trigger it. If the accept
statement includes a local name, then this local name will hold whichever signal instance is actually
received. The type of such a local name is the effective common ancestor of the listed signals (as
defined in Subclause 8.7), if one exists, and is untyped otherwise.
For example:
accept (sig: SignalNewArrival, SignalTermination);
if (sig instanceof SignalNewArrival) {
WriteLine(((SignalNewArrival)sig).name);
terminate = false;
} else {
terminate = true;
}
For a compound accept statement, a local named defined in an accept clause (such as arrival in the
example above) is available only in the body of that clause and is considered unassigned after the
accept statement. New local names may be defined within the accept statement (such as terminate in
the example above), but only if the same names are defined in every block of the accept statement.
After the accept statement, such new local names have a type that is the effective common ancestor (as
defined in Subclause 8.7) of its type in each of the blocks of the accept statement, if one exists, and is
untyped otherwise.
Syntax
ClassifyStatement(s: ClassifyStatement)
= "classify" Expression(s.expression) ClassificationClause(s) ";"
ClassificationClause(s: ClassifyStatement)
= ClassificationFromClause(s.fromList)
[ ClassificationToClause(s.toList) ]
| [ ReclassifyAllClause (s.isReclassifyAll=true) ]
ClassificationToClause(s.toList)
ClassificationFromClause(qList: QualifiedNameList)
= "from" QualifiedNameList(qList)
ClassificationToClause(qList: QualifiedNameList)
= "to" QualifiedNameList(qList)
ReclassifyAllClause(qList: QualifiedNameList)
= "from" "*"
10.1 Overview
Units are lexically independent (though semantically related) segments of Alf text that provide a level of
granularity similar to typical programming language text files. A unit may also have subunits that define
namespaces that are owned (directly or indirectly) by the unit but whose Alf definition is given by a unit
that is textually separate from the base unit. Inclusion in the base unit is indicated using a stub
declaration in the base unit and a namespace declaration in the definition of the subunit.
Since an Alf unit can be processed into a UML abstract syntax representation, a portion of a model
represented in Alf can always be integrated into a larger model on that basis, regardless of the surface
representation of any portion of the model.
Examples
private import ProductSpecification::Product; // Element import
private import EE_OnlineCustomer as OL_Customer; // Element import with alias
private import DomainDataTypes::*; // Package import
package Ordering // Unit definition
{
class Order; // Stub declaration
}
namespace Ordering; // Namespace declaration
public import Customer; // Public element import
/** Order class of the Ordering subsystem. */ // Documentation comment
class Order { // Subunit definition
...
}
@apply(DataProfile) // Profile application
@Entity(tableName=>"CustomerTable") // Stereotype annotation
class Customer {
...
}
The subunit defining class Order must then have a corresponding namespace declaration indicating that
it is completing a stub in the namespace Ordering.
namespace Ordering; // Namespace declaration
class Order { // Subunit definition
…
}
(See the subclause for each kind of namespace definition for further discussion of stub declarations.)
Model Units
An Alf model unit is an Alf unit that is not a subunit of any other Alf unit. It may be used to represent
the model of a classifier or package that is intended to be individually referenced as a named element.
A model unit is not required to have a namespace declaration. But, if it does have such a declaration,
then, by definition, the referenced namespace will not be represented using Alf. If it does not have a
namespace declaration, then which namespace it is placed in, if any, is tool specific.
A model unit may represent an entire UML model (at least within the limits of the fUML subset) or it
may represent a model element (such as a class or standalone activity) intended to be used within some
larger model. The Alf specification does not define how such an Alf unit is created within a specific
modeling environment or how it is attached to some larger model within the environment. It does,
however, place requirements on the modeling environment to allow references from within Alf units to
named elements defined in namespaces outside of those units (see Subclause 10.2).
Import Declarations
An import declaration specifies a UML import dependency (see UML Superstructure, Subclauses 7.3.15
and 7.3.39). Such a declaration may specify an element import or a package import, and it may be
public or private. Alf notation only provides for import declarations on namespaces defined as units.
The import declarations for a unit are placed after the namespace declaration (if any) and before any
stereotype annotations and the body of the definition for the unit. The qualified name given in an import
declaration must be a fully qualified name (as defined in Subclause 8.2).
For an element import reference:
This declaration specifies that the element with the qualified name ProductSpecification::Product
be included as a member of the namespace Ordering. Since this is a private import, the element is
imported as a private member and is not visible outside Ordering. On the other hand, a public import
such as
public import ProductSpecification::Product; // Public element import
package Ordering { // Namespace definition
…
}
specifies that the element be imported as a public member of Ordering. In this case, the qualified name
Ordering::Product refers to the same element as ProductSpecification::Product.
In this case, within the Ordering namespace, the unqualified name for
ProductSpecification::Product is Prod, not Product. Further, since the import is public, outside
Ordering the qualified name Ordering::Prod can be used to refer to the same element as
ProductSpecification::Product.
A package import declaration may be used to import all the elements of a package. For example, the
following declaration:
private import ProductSpecification::*; // Package import
package Ordering { // Namespace definition
…
}
specifies that all the elements of the package ProductSpecification should be imported into the
namespace Ordering as private members. This is equivalent to giving a private element import
declaration for each of the elements in ProductSpecification. As with an element import declaration,
a package import may also be public. However, aliases cannot be defined with a package import.
The first special case shown in Table 10-7 is for denoting the application of a profile. For cases other
than the standard UML profiles, such a profile application annotation for the profile must appear before
the stereotypes for the profile are used in stereotype annotations. Once a profile is applied to a unit,
however, it is also available without further application to all subunits of that unit.
NOTE. The actual definition of specific kinds of named elements allowed in various kinds of
namespaces is given in the following subclauses. However, the syntax and semantics of visibility are
discussed here, because they are largely common across the different kinds of named element
definitions.
10.3 Packages
A package is a namespace whose sole function is to group its member elements, which must be
packageable elements. In Alf, the supported kinds of packageable element definitions are just the
namespace definitions for packages and the various kinds of classifiers (see Subclause 10.4). Note also
that only packageable elements may be imported into other namespaces (see Subclause 10.1).
A packageable element may be fully defined within the textual body of a package definition.
Alternatively, a stub declaration may be given for the element, which includes only the element name
and visibility (and, for an activity, its signature). The full definition of the element is then given in a
subunit definition (see Subclause 10.1).
Examples
package Ordering // Base unit
{
public assoc Selects // Nested namespace
{
public cart: ShoppingCart[0..*];
public selectedProducts: Product[1..*];
public selectionInfo: ProductSelection;
}
Syntax
PackageDeclaration(d: PackageDefinition)
= "package" Name(d.name)
PackageDefinition(d: PackageDefinition)
= PackageDeclaration(d) "{" { PackagedElement(d.ownedMember) } "}"
PackagedElement(m: Member)
= [ DocumentationComment(m.documentation) ]
{ StereotypeAnnotation(m.annotation) }
ImportVisibilityIndicator(m.visibility) PackagedElementDefinition(m)
10.4 Classifiers
10.4.1 Overview
A classifier specifies a classification of instances according to their features. Classifiers may participate
in generalization relationships, which can result in its feature elements being inherited. Alf supports the
following kinds of classifier: classes (including active classes), structured data types, enumerations,
associations, signals and activities. This subclause specifies how each kind of classifier may be defined
in Alf.
A classifier template parameter may optionally be constrained, such that any valid argument for the
parameter must conform to a given classifier. If a parameter is so constrained, then the constraining
classifier ia named in a specialization clause for that parameter.
For example, a template class with the signature Sorter<T>, then T could be bound to any classifier for
T. However, if the signature was Sorter<T specializes Comparable>, then T could only be legally
bound to a class that was a subclass (directly or indirectly) of the class Comparable.
NOTE. Classifier templates are specified in the UML Superstructure, Subclause 17.5.7, with classifier
template parameters described in Subclause 17.5.8. For classifier template parameters mapped from Alf,
the allowSubstituable property is always false.
Within the body of the definition of a classifier with template parameters, the parameters may be used as
types. If a parameter is not constrained, then it is treated as if it was a data type with no attributes or
operations. If the parameter is constrained, then it is considered to be the same kind of classifier as its
constraining classifiers and to specialize the constraining classifier. Template parameters are always
considered to be abstract classifiers that may not be directly instantiated, since any parameter could be
substituted with an actual argument that is abstract. Template parameters are not visible outside of the
classifier definition.
NOTE. The allowance for substituting a classifier template parameter without a constraining classifier
with a classifier of any kind, regardless of the kind of parameterable element the template has, is a
semantic variation point given in UML Superstructure Subclause 17.5.7. This allowance is necessary in
order to provide for parameterized types that may be instantiated with any kind of argument type. The
notational default for an unconstrained classifier template parameter is specified in UML Superstructure
Subclause 17.5.8 to be that it is considered to have a parameterable element that is a class. However,
presuming, instead, that it is an abstract data type, as given above, prevents it from being used in places
that require a class, which would result in an ill-formed model if the parameter was substituted with a
type other than a class. There are no instances in the Alf notation in which an abstract data type (with no
attributes or operations) may be used, but some other kind of classifier could not be used in the same
place.
When the template classifier is instantiated and its parameters are bound, the result is effectively an
equivalent bound element in which all of the template parameters have been replaced with the
arguments to which they are bound (see Subclause 6.2 on the copy semantics of templates). A template
parameter without a constraining classifier may actually be bound to an argument that is any kind of
classifier, not just a class, as long as this would not make the equivalent bound element ill formed. A
template parameter with a constraining classifier must be bound to an argument classifier that conforms
to the constraining classifier.
Syntax
ClassDeclaration(d: ClassDefinition)
= [ "abstract" (d.isAbstract=true) ] "class" ClassifierSignature(d)
In the above example, the activity getSingleton is nested in the class Singleton. Because of this, it
has visibility to the private constructor for Singleton, which is not visible outside of the class.
Any member definition of a class may be preceded by a documentation comment (see Subclause 7.4.2)
that is attached to the element being defined.
A member definition may also have one or more stereotype annotations applied to it. Such annotations
have the same semantics as annotations made on a unit definition (see Subclause 10.1), except that the
qualified names do not need to be fully qualified and are resolved in the current scope of the enclosing
class, rather than in model scope. If the class member definition is a stub declaration, then the annotation
for a stereotype may be applied either to the stub declaration or the subunit definition, but not both.
Class Specialization
A class may specialize one or more other classes, in which case it inherits members from the classes it
specializes (its superclasses). Each of the names in the specialization part of a class definition must
resolve to a class. The visibility of inherited members from the classes named in the specialization part
is as specified in the UML Superstructure, Subclause 7.3.8, Classifier.
All non-private members of superclasses are inheritable, except for operations redefined in the subclass
(see Subclause 10.5.3). However, all members of a namespace must be distinguishable. It is therefore
not legal to define a class to inherit members that are not distinguishable.
By default, two named elements are distinguishable if they are either different kinds of elements (e.g., a
property as opposed to an operation) or they have different names. However, operations with the same
name may be distinguished if they have different signatures (see Subclause 10.5.3). Such operations are
said to be overloaded.
NOTE. Alf does not allow the redefinition of any kinds of class members other than operations, because
this is the only kind of redefinition allowed in the fUML subset (see fUML Specification, Subclause
7.2.2). The constraint on distinguishability of namespace members is given in Subclause 7.3.34 of the
UML Superstructure. The default definition for distinguishability of named elements is given in
Subclause 7.3.33 of the UML Superstructure. The rule for the distinguishability for operations is that
} // No additional behavior
Syntax
ActiveClassDeclaration(d: ActiveClassDefinition)
= [ "abstract" (d.isAbstract=true) ] "active" "class"
ClassifierSignature(d)
ActiveClassDefinition(d: ActiveClassDefinition)
= ActiveClassDeclaration(d) "{" { ActiveClassMember(d.ownedMember) }
"}" [ "do" BehaviorClause(d.classifierBehavior)
(d.classifierBehavior.visibility="private")
(d.ownedMember->includes(d.classifierBehavior)) ]
BehaviorClause(a: ActivityDefinition)
= Block(a.body)
| Name(a.name) (a.isStub=true)
Syntax
DataTypeDeclaration(d: DataTypeDefinition)
= [ "abstract" (d.isAbstract=true) ] "datatype" ClassifierSignature(d)
DataTypeDefinition(d: DataTypeDefinition)
= DataTypeDeclaration(d) "{" { StructuredMember(d.ownedMember) } "}"
StructuredMember(m: Member)
= [ DocumentationComment(m.documentations ]
{ StereotypeAnnotation(m.annotations) } [ "public"(m.visibility) ]
PropertyDefinition(m)
10.4.5 Associations
An association is a classifier that specifies a semantic relationship that may exist between two or more
instances. The instances of an association are known as links. The features of an association must all be
properties (see Subclause 10.5.2).
Syntax
AssociationDeclaration(d: AssociationDefinition)
= [ "abstract" (d.isAbstract=true) ] "assoc" ClassifierSignature(d)
AssociationDefinition(d: AssociationDefinition)
= AssociationDeclaration(d) "{" StructuredElement(d.ownedMember)
StructuredElement(d.ownedMember) { StructuredElement(d.ownedMember) }
"}"
10.4.6 Enumerations
An enumeration is a classifier whose allowed instances are a specified set of enumeration literals.
Examples
enum TrafficLightColor { RED, YELLOW, GREEN }
Syntax
EnumerationDeclaration(d: EnumerationDefinition)
= "enum" Name(d.name) [ SpecializationClause(d.specialization) ]
EnumerationDefinition(d: EnumerationDefinition)
= EnumerationDeclaration(d) "{" EnumerationLiteralName(d.ownedElement)
{ "," EnumerationLiteralName(d.ownedElement) } "}"
EnumerationLiteralName(m: EnumerationLiteralName)
= [ DocumentationComment(m.documentation) ]
Name(m.name) (m.visibility="public")
NOTE. Enumerations cannot have template parameters, since there would not be any way to use them
within the enumeration definition.
10.4.7 Signals
A signal is a classifier whose instances may be sent asynchronously (see Subclause 8.3.10) to an active
object (see also Subclause 10.4.3). The ability for an object to receive a certain signal is specified using
Syntax
SignalDeclaration(d: SignalDefinition)
= [ "abstract" (d.isAbstract=true) ] "signal" ClassifierSignature(d)
SignalDefinition(d: SignalDefinition)
= SignalDeclaration(d) "{" { StructuredElement(d.ownedMember) } "}"
10.4.8 Activities
An activity is “the specification of parameterized behavior as the coordinated sequencing of subordinate
units whose individual elements are actions” (UML Superstructure, Subclause 12.3.4). It is the
fundamental mechanism for behavioral modeling in Alf.
Activities are namespaces (see Subclause 10.2) that may be defined as Alf units (see Subclause 10.1).
Activities may also be implicitly defined by the in-line specification of behavior for active classes (see
Subclause 10.4.3) or operations (see Subclause 10.5.3).
In UML, activities are also classes (see UML Superstructure, Subclause 12.3.4) and so may have
attributes, operations and specialization. However, for simplicitly, Alf does not provide a textual
notation for features and specializations on activities. Instead, an active class may be used to model
structural features along with a related behavior (see Subclause 10.4.3).
Examples
activity getNodeActivations
(in node: ActivityNode): ActivityNodeActivation[*] {
return this.activations -> select a (a.node == node);
}
do {
accept (PaymentDeclined) {
declined = true;
this.declineCharge();
} or accept (PaymentApproved) {
declined = false;
}
} while (declined);
this.packAndShip();
accept (OrderDelivery);
this.notifyOfDelivery();
}
Syntax
ActivityDeclaration(d: ActivityDefinition)
= "activity" Name(d.name) [ TemplateParameters(d) ] FormalParameters(d)
[ ReturnParameter(d.ownedMember) ]
ActivityDefinition(d: ActivityDefinition)
= ActivityDeclaration(d) Block(d.body)
FormalParameters(d: NamespaceDefinition)
= "(" [ FormalParameterList(d) ] ")"
FormalParameterList(d: NamespaceDefinition)
= FormalParameter(d.ownedMember) { "," FormalParameter(d.ownedMember) }
FormalParameter(p: FormalParameter)
= [ DocumentationComment(p.documentations) ]
{ StereotypeAnnotation(p.annotations) }
ParameterDirection(p.direction) Name(p.name) ":"
TypePart(p)
Cross References
1. Member see Subclause 10.2
2. AttributeDefinition see Subclause 10.5.2
3. OperationDefinition see Subclause 10.5.3
4. OperationStubDeclaration see Subclause 10.5.3
5. ConstructorDefinition see Subclause 10.5.3.1
6. ConstructorStubDeclaration see Subclause 10.5.3.1
7. DestructorDefinition see Subclause 10.5.3.2
8. DestructorStubDeclaration see Subclause 10.5.3.2
9. ReceptionDefinition see Subclause 10.5.4
10. SignalReceptionDefinition see Subclause 10.5.4
11. SignalReceptionStubDeclaration see Subclause 10.5.4
Semantics
See the discussion of the semantics of each kind of feature in subsequent subclauses.
10.5.2 Properties
A property is a structural feature of a classifier. The attributes of classes, data types and signals are
properties, as are the association ends of an association.
Example
amount: Money = 0;
products: Product [1..*] ordered;
wheels: compose Wheel [2..4];
Syntax
PropertyDefinition(d: PropertyDefinition)
= PropertyDeclaration(d) ";"
AttributeDefinition(d: PropertyDefinition)
= PropertyDeclaration(d) [ AttributeInitializer(d.initializer) ] ";"
AttributeInitializer(e: Expression)
= "=" InitializationExpression(e)
PropertyDeclaration(d: PropertyDefinition)
= Name(d.name) ":" [ "compose" (d.isComposite=true) ] TypePart(d)
TypePart(d: TypedElementDefinition)
= TypeName(d.typeName) [ Multiplicity(d) ]
Multiplicity(d: TypedElementDefinition)
= MultiplicityRange(d) [ OrderingAndUniqueness(d) ]
OrderingAndUniqueness(d: TypedElementDefinition)
= "ordered" (d.isOrdered=true) [ "nonunique" (d.isNonunique=true) ]
| "nonunique" (d.isNonunique=true) [ "ordered" (d.isOrdered=true) ]
| "sequence" (d.isOrdered=true and d.isNonunique=true)
MultiplicityRange(d: TypedElementDefinition)
= MultiplicityIndicator (d.upperBound="*")
| "[" [ DecimalLiteral(d.lowerBound) ".." ]
UnlimitedNaturalLiteral(d.upperBound) "]"
UnlimitedNaturalLiteral(v: String)
= DecimalLiteral(v)
| UnboundedValueLiteral(v)
The Alf notation for properties is thus similar to the usual notation used in UML diagrams. For example,
the property definition
items: Item [0..*] ordered nonunique;
declares a property that can hold zero or more objects of type Item in an ordered sequence. If the
multiplicity is [0..*], then a shorter form can also be used in which the range 0..* is implicit:
items: Item[] ordered nonunique;
In addition, the single keyword “sequence” may be used in place of the combination of the two
keywords “ordered” and “nonunique”. Thus, the following is also equivalent to the declarations above:
items: Item[] sequence;
When an instance of class C is destroyed, the object it holds for attribute b will also be automatically
destroyed, but the object it holds for attribute a will not.
Composition properties can also be included in association definitions. For example:
assoc R {
public c: C;
public d: compose D;
}
Note that (per UML Superstructure, Subclause 7.3.3) the composition annotation is on the part end of
the composite association. That is, in the above association, c is the composite while d is the part. Thus,
when an instance of class C is destroyed, if there is a link of association R with that object at one end,
then that link and the instance of D at the other end will also be destroyed.
NOTE. Alf provides no notation for shared aggregation, since this has no semantic effect. However,
properties specified outside of Alf notation with aggregation=shared are treated the same way as
properties with aggregation=none.
Attribute Initialization
The attributes of a class are properties (see Subclause 10.4.2). However, unlike the case of other
property definitions, Alf provides a notation for the initializer of an attribute, which is an expression that
is evaluated every time the class containing the attribute is instantiated, with the result being assigned to
the attribute. The enclosing class is the current scope for names in the expression. The evaluation of
initializers is carried out as part of the execution of the creation of a newly instantiated object (see
Subclause 8.3.12 on the creation of objects and Subclause 10.5.3.1 on constructors).
NOTE. The fUML subset does not include default values for properties (see fUML Specification,
Subclause 7.2.2). However, the evaluation of attribute initializer expressions in Alf are mapped as part
of the constructor for the enclosing class that owns the attribute, which can be executed within the
fUML subset. The attribute initializers themselves do not need to be referenced during model execution.
Instance creation (see Subclause 8.3.12) and sequence construction (see Subclause 8.3.15) expressions
use as initializers may be written in the shorthand initialization expression form, as for a local name
declaration statement (see Subclause 9.6). For example, the attribute definition
position: Point = new(0,0);
is equivalent to
position: Point = new Point(0,0);
is equivalent to
colors: Set<Color> = Set<Color>{ Color::red, Color::blue, Color::green };
10.5.3 Operations
An operation is a behavioral feature of a class that provides the specification for invoking an associated
method behavior. Only classes may have operations as features. An operation is called on an instance of
a class that has it as a feature using an invocation expression (see Subclause 8.3.10).
Examples
// Abstract operation
abstract select(in cart: Cart, in product: Product, in quantity: Count);
// In-line definition
select(in cart: Cart, in product: Product, in quantity: Count) {
Selects.createLink(cart, product, this);
this.quantity = quantity;
this.unitPriceOfSelection = product.getUnitPrice();
}
// Stub declaration
unitPrice(): Money redefines Selection::getUnitPriceOfSelection;
Syntax
OperationDeclaration(d: OperationDefinition)
= [ "abstract" (d.isAbstract=true) ] Name(d.name)
FormalParameters(d.ownedMember) [ ReturnParameter(d.ownedMember) ]
[ RedefinitionClause(d.redefinition) ]
OperationDefinition(d: OperationDefinition)
= OperationDeclaration(d) Block(d.body)
OperationStubDeclaration(d: OperationDefinition)
= OperationDeclaration(d) ";" (d.isStub=true)
RedefinitionClause(qList: QualifiedNameList)
= "redefines" QualifiedNameList(qList)
A formal parameter may also have one or more stereotype annotations applied to it. Such annotations
have the same semantics as annotations made on a unit definition (see Subclause 10.1), except that the
qualified names do not need to be fully qualified and are resolved in the current scope of the enclosing
activity, rather than in model scope.
Operation Distinguishability
Two operations are considered distinguishable within the same namespace if they have different names
or different signatures. It is illegal to define two indistinguishable operations within the same class.
For example:
class C {
f (in x: Integer): Integer;
f (in x: Boolean): Integer; // Legal, different parameter type.
f (in x: Integer): Boolean; // Legal, different return type.
f (out x: Integer): Integer; // Illegal! Parameter types are the same.
}
The first three operations above are distinguishable, even though they have the same name. They are
said to be overloaded. The last operation, however, has the same signature as the first one, and is
therefore illegal in the same class.
NOTE. The rule for distinguishability of operations is defined in general for behavioral features in
Subclause 7.3.5 of the UML Superstructure. The requirement for distinguishability of namespace
members is given in Subclause 7.3.34 of the UML Superstructure.
Note that, in this case, it would be illegal to redefine only one of A::p and B::p with an
indistinguishable operation, since then the other superclass operation would still be inherited and would
conflict with the redefining operation in C.
In the case of the explicit definition, it would also be possible to give the operation in C a different name:
class C specializes A,B {
renamed(in x: Integer) redefines A::p, B::p;
}
Note that, in this case, the operations A::p and B::p are still not inherited by C—C has no operation
called p. On the other hand, in
class C specializes A,B {
renamed(in x: Integer) redefines A::p;
}
only A::p is redefined in C, as renamed, and B::p is, therefore, still inherited. But there is no name
conflict, and C will have both an operation called renamed and an inherited operation called p.
NOTE. The rule for consistency between redefined and redefining operations is given in Subclause
7.3.36 of the UML Superstructure. The general UML rule is that the types of the redefining operation
must conform to the types of the redefined operation. Unfortunately, this does not take into account the
directions of the parameters. Alf requires that the redefining operation have parameters with the same
types and directions as the redefined operation.
10.5.3.1 Constructors
A constructor is an operation, specially identified using the @Create stereotype annotation (see
Subclause 10.1), and used to initialize a newly created object. The constructor to be used for this
purpose is given in the instance creation expression that creates the object (see Subclause 8.3.12).
NOTE. Constructor operations are discussed in the UML Superstructure specification primarly in the
context of composite structure (see UML Superstructure, Subclause 9.3.1). However, the «Create»
stereotype is generally available to annotate a constructor operation (see UML Superstructure, Subclause
C.1). An Alf constructor maps to an operation with this stereotype. Strictly, the use of this stereotype is
outside the fUML subset. However, the stereotype is only used to signal that the annotated operation
may be used in an instance creation expression. The actual mapping for an instance creation expression
results in a create object action with a regular operation call on the constructor, which may be executed
within the fUML subset (see Subclause 8.3.12).
Examples
@Create public Table(in rows: Integer, in columns: Integer);
@Create
public ProductSelection
(in cart: Cart, in product: Product, in quantity: Count);
@Create
private registered() {
Repository::get().register(this);
}
Semantics
Default Constructors
Every class represented in Alf notation (see Subclause 10.4.2) is always mapped as having at least one
constructor. If no constructor is explicitly defined for the class, then the class is assumed to have a
default constructor. The name of the default constructor is the same as the name of the class.
An object created with the expression new Initialization() has a with value 0 (since b has not been
initialized yet) and b with value 1.
Explicit Constructors
An explicit constructor definition has the same syntax as a regular operation definition, with the
stereotype annotation @Create. An explicit constructor may have the name of its class, like a default
constructor. However, it may also have a different name than that of its class, in which case the
constructor is explicitly identified by name when used in an instance creation expression (see Subclause
8.3.12).
If a class has an explicit constructor definition, then the default constructor is no longer available, even
if the defined constructor has a different name than the default constructor.
A constructor may also have parameters, but no return type is explicitly given. Implicitly, every
constructor has the class it is constructing as its return type. This implicit return type is included in the
signature for the constructor.
A class may have more than one constructor, any of which may be used in an instance creation
expression for objects of the class.
As operations, non-private constructors are inheritable and the usual distinguishability rules apply (see
Subclause 10.5.3). Note that constructors from different classes are always distinguishable, though,
because at least their return types will be different.
Unlike a normal operation, a constructor may not be redefined in a subclass. Only a constructor directly
owned by a class may be used in an instance creation expression for an instance of the class (see
Subclause 8.3.12).
When an object is initialized using an explicit constructor, the default constructor attribute initialization
behavior (as described above) is always performed before the explicit constructor behavior. For
example, suppose the above example were modified as shown below.
class Initialization {
public a: Integer;
public b: Integer = 1;
The creation expression new Initialization() now results in an object having a with value 1, since
attribute b is initialized before the body of the constructor is executed.
The body of a constructor may contain an alternative constructor invocation for another constructor in
the same class or super constructor invocations for constructors in immediate superclasses. The syntax
for such invocations is the same as a normal operation invocation (see Subclauses 8.3.10 and 8.3.11). In
addition, only within a constructor body, the symbol “this” may be used as an alternative constructor
invocation target, with the same meaning as invoking a constructor with the same name as the class. If
the class has exactly one superclass, then the symbol “super” may also be used as a super constructor
invocation target, with the same meaning as invoking a constructor on the superclass with the same
name as the superclass.
For example, the following class definition contains an explicit invocation of one of its own constructors
and one from its superclass.
class B specializes A {
@Create public B(in x: Integer) {
super.A(x);
}
Using the special invocation syntax allowed in constructors, this could also be written as follows.
class B specializes A {
@Create public B(in x: Integer) {
super(x);
}
An alternative constructor invocation may only occur as the first statement of the body of a constructor
(as specified in the static semantics for feature invocation expressions in Subclause 8.3.10). Super
constructor invocations must all occur at the beginning of the body of a constructor, with no other
statements preceding them, and no more than one invocation for each superclass (as specified in the
static semantics for super invocation expressions in Subclause 8.3.11).
In the absence of explicit constructor invocations at the start of a constructor body (and also in the case
of the default constructor behavior), a super constructor invocation is made implicitly for each
immediate superclass, in the order the superclasses appear in the specializes list of the class
containing the constructor, before executing any statements in the constructor body. If the constructor
body begins with explicit superclass constructor invocations for some but not all superclasses of the
10.5.3.2 Destructors
A destructor is an operation, specially identified using the @Destroy stereotype annotation (see
Subclause 10.1), used to clean up an object that is to be destroyed. A call to a destructor not only
invokes the destructor’s behavior, but also results in the actual destruction of the object (see the
semantics of destructor invocation under Subclauses 8.3.10 and 8.3.11).
NOTE. The UML Superstructure specification defines the «Destroy» stereotype to annotate a
destructor operation (see Subclause C.1). An Alf destructor maps to an operation with this stereotype.
Strictly, the use of this stereotype is outside the fUML subset. However, the stereotype is only used to
signal that the annotated operation may be used in an instance destruction expression. The actual
mapping for an instance destruction expression results in a regular operation call on the destructor,
which may be executed within the fUML subset, followed by a destroy object action (see Subclauses
8.3.10 and 8.3.11).
Examples
@Destroy public ProductSelection();
@Destroy
private unregister() {
Repository::get().unregister(this);
super.destroy();
}
Semantics
Default Destructors
Every class represented in Alf notation (see Subclause 10.4.2) is always mapped as having at least one
destructor. If no destructor is explicitly defined for the class, then the class is assumed to have a default
constructor. The name of the default destructor is “destroy”.
NOTE. This means that a call to the default destructor destroy is always an explicit destructor call, not
an implicit destructor invocation as defined in Subclause 8.3.10.
The behavior of the default destructor is to first call the destructor destroy() (i.e., with no arguments)
on any immediate superclasses (if such exists), in the order in which those superclasses are given in the
specializes list for the class of the object being destroyed. The destroy() destructor (if it exists) is
then called on any object that is the value of a composite attribute or on the opposite end of a composite
association. Destructors are called on attributes in the order in which they are defined in the class of the
object being destroyed. The order in which destructors are called on objects related by composite
association is not specified.
Explicit Destructors
An explicit destructor definition has the same syntax as a regular operation definition, with the
stereotype @Destroy. The name of the destructor may then be used in an invocation expression to
destroy an object of the class (see Subclause 8.3.10).
If a class has an explicit destructor definition, then the default destructor is no longer available, even if
the defined destructor has a different name than destroy.
10.5.4 Receptions
A reception is a behavioral feature of an active class that declares that instances of the class are prepared
to react to the receipt of a specific signal. Only active classes may have receptions as features. Normally,
the signal is defined separately and referenced by name in the reception declaration. As a convenience,
Alf also allows the definition of the signal and a declaration of a reception of it to be combined into a
signal reception definition.
Examples
receive Checkout;
receive signal SubmitCharge {
public accountNumber: BankCardAccountNumber;
public billingAddress: MailingAddress;
public cardExpirationDate: MonthYear;
public cardholderName: PersonalName;
}
Figure 10-72 Abstract Syntax of Reception Definitions and Signal Reception Definitions
Cross References
1. Name see Subclause 7.5
2. QualifiedName see Subclause 8.2
3. Member see Subclause 10.2
4. SpecializationClause see Subclause 10.4.2
5. StructuredElement see Subclause 10.4.4
6. SignalDefinition see Subclause 10.4.7
Semantics
The owning classifier definition of a reception definition or a signal reception definition must be for an
active class. An invocation of a reception on an instance of the owning active class results in a sending
of the specified signal to that instance (see Subclause 8.3.10).
Reception Definitions
The name in a reception definition must be the visible name of a signal.
The reception is given the same name as the base name of the signal without any qualification. Since
receptions must be distinguished by name, this means that no active class may have more than one
reception (inherited or owned) for a signal with a given name.
is equivalent to:
active class Order {
receive SubmitCharge;
signal SubmitCharge {
public accountNumber: BankCardAccountNumber;
public billingAddress: MailingAddress;
public cardExpirationDate: MonthYear;
public cardholderName: PersonalName;
}
Note that, even though the reception and the signal have the same name, there is no distinguishability
conflict, because receptions and signals are separate syntactic types. The name Order::SubmitCharge
in this example can thus refer to either the reception or the signal, depending on context.
Since the result of the call to including is untyped, it is not assignable to extendedList, which has type
Integer. Instead, an explicit cast must be used:
let extendedList: Integer[] = (Integer)_including(integerList, 1); // Legal
To avoid having to do this, the template function behaviors in the CollectionFunctions package (see
Subclause 11.5) should generally be used in preference to the primitive behaviors defined in the
SequenceFunctions package. Note, however, that these template functions are actually defined in
terms of the primitive sequence functions, since only non-template primitive behavior implementations
can be registered with the fUML execution locus.
is equivalent to
let extendedList: Integer[] = including<Integer>(integerList, 1);
Since the result type of including<Integer> is Integer, the right-hand side of this statement is
assignable to the left-hand side without the need for an explicit cast.
Each of the functions defined in the SequenceFunctions package has a template version defined as an
activity in the CollectionFunctions package. The body of this activity simply calls the corresponding
primitive function and returns the result of that call, cast to the appropriate result type. For example, the
including function may be defined as follows as an Alf unit (see Subclause 10.4.8 on activity
definitions):
The in-place functions cannot be used with collection objects, since the inout parameter cannot be
assigned back to the collection object. However, all collection classes have regular operations that
correspond to the functionality of the “in place” functions (see Subclause 11.6). The in-place collection
functions are intended to provide similar functionality for sequences to that provided by the similarly
named operations on collection objects.
Generalizations
• Collection<T>
Operations
[1] add ( in element : T ) : Boolean
Insert the given element into this bag. Always returns true.
[4] destroy ( )
Destroy this bag.
11.6.2 Collection<T>
An abstract collection of elements of a specified type <T>. Various concrete subclasses support ordered
and unordered collections, with and without duplicates allowed.
Generalizations
None
Operations
[1] add ( in element : T ) : Boolean
Insert the given element into this collection. Return true if a new element is actually inserted.
[3] clear ( )
Remove all elements from this collection.
11.6.3 Deque<T>
Double-Ended Queue (pronounced "deck"). Concrete ordered, nonunique collection. Supports duplicate
entries. Ordered by position. Insertion and removal can occur at the front or the back of a deque. Can
operate as FIFO (in at back, out at front). Can operate as Stack (in at front/back, out at front/back).
Generalizations
• Queue<T>
Operations
[1] addFirst ( in element : T ) : Boolean
Add element into this deque at the front. Always returns true.
[3] destroy ( )
Destroy this deque.
pre: self.notEmpty()
post: result = self.toSequence()->last()
pre: self.notEmpty()
post: result = [email protected]()->last() and
self.toSequence() = [email protected]>subSequence(1,[email protected]()-1)
pre: self.includes(element)
post: result = element and
let revSeq = [email protected]()->reverse() in
let index = revSeq.indexOf(element) in
self.toSequence() = revSeq->subSequence(1,index-1)->union(revSeq-
>subSequence(index+1,revSeq->size()))->reverse()
11.6.4 Entry
An association of value to key. Note that entries are data values that are always passed by copy.
Changing an entry returned outside of a map will NOT effect the association within the map.
Generalizations
None
Attributes
• key : Key
11.6.5 List<T>
Concrete ordered, nonunique collection. Supports duplicate entries. Ordered by position in list.
Generalizations
• Bag<T>
Operations
[1] add ( in element : T ) : Boolean
Append the given element into this list at the end. Always returns true.
pre: self.notEmpty()
post: result = [email protected]()->first()
pre: self.includes(element)
post: result = [email protected]() -> indexOf(element)
pre: self.notEmpty()
post: result = [email protected]()->first()
post: self.toSequence()
= seq->iterate(element; s = [email protected]() | s->excluding(element))
post: self.toSequence() =
let preSeq = [email protected]() in
if result then
let index = [email protected](element) in
self.toSequence() = preSeq->subSequence(1, index-1)->
union(preSeq->subSequence(index+1, [email protected]()))
else preSeq endif
Dictionary of key and value pairs called "entries". Concrete unordered, unique (by key) collection.
Generalizations
None
Operations
[1] clear ( )
Remove all entries in this map.
post: self.isEmpty()
[2] destroy ( )
Destroy this map.
post: result.equals(self.toSequence())
pre: self.keys().toSequence()->includes(key)
post: result = self.toSequence()->select(e | e.key = key).value
post: result.equals(self.toSequence().key)
pre: entries->isUnique(key)
post: result.toSequence()->asSet() = sequence->asSet()
pre: entries->isUnique(key)
post: self.toSequence().key->asSet() = [email protected]().key->asSet()->union(entries->asSet())
and
self.toSequence()->isUnique(key) and
self.keys().toSequence()->forAll(k | self.get(k) =
if entries.key->includes(k) then entries->select(key=k)
else [email protected](k))
pre: self.includesKey(key)
post: result = [email protected](key) and
self.toSequence()->isUnique(key) and
self.toSequence()->asSet() = [email protected]()->reject(e | e.key = key)->asSet()
post: result.equals(self.toSequence().value)
11.6.7 OrderedSet<T>
Concrete ordered, unique collection. Does not support duplicate entries. Ordered by position.
Generalizations
• Set<T>
Operations
[1] add ( in element : T ) : Boolean
Append the given element into this ordered set at the end. Return true if a new element is actually
inserted.
[6] destroy ( )
Destroy this ordered set.
pre: self.notEmpty()
post: result = [email protected]()->first()
pre: self.includes(element)
post: result = [email protected]() -> indexOf(element)
pre: self.notEmpty()
post: result = [email protected]()->last()
11.6.8 Queue<T>
First In First Out Queue. Concrete ordered, nonunique collection. Supports duplicate entries. Ordered by
position. Considering the queue as a sequence, insertion occurs at the back of the queue, removal at the
front.
Generalizations
• Collection<T>
Operations
[1] add ( in element : T ) : Boolean
Add the given element into this queue at the back. Always returns true.
[4] destroy ( )
Destroys this queue.
pre: self.notEmpty()
post: result = self.toSequence()->first()
post: self.toSequence()
= seq->iterate(element; s = [email protected]() | s->excluding(element))
pre: self.notEmpty()
post: result = [email protected]()->first() and
pre: self.includes(element)
post: result = element and
let preSeq = [email protected]() in
let index = preSeq.indexOf(element) in
self.toSequence() = preSeq->subSequence(1,index-1)->union(preSeq-
>subSequence(index+1,preSeq->size()))
post: self.toSequence() =
let preSeq = [email protected]() in
if result then
let index = [email protected](element) in
self.toSequence() = preSeq->subSequence(1, index-1)->
union(preSeq->subSequence(index+1, [email protected]()))
else preSeq endif
11.6.9 Set<T>
Generalizations
• Collection<T>
Operations
[1] add ( in element : T ) : Boolean
Insert the given element into this set. Return true if a new element is actually inserted.
[4] destroy ( )
Destroy this set.
12.1 Overview
The Alf::Syntax::Common package contains the root abstract classes SyntaxElement and
DocumentedElement. It also contains common ElementReference and AssignedSource classes that
are used throughout the rest of the abstract syntax model. Element reference and assigned source objects
are not themselves syntax elements but, rather, represent certain relevant information determined during
the static semantic analysis of an abstract syntax tree and associated with elements of that tree.
The mapping of common elements to UML is given in Clause 16.
Element References
As discussed in Subclauses 8.2 and 10.2, a name resolves to the model element that it names. If this
model element is defined outside the context of the Alf text in which the reference to its name appears,
then the resolution is straightforward. However, the situation is more complicated if the element being
referenced is defined within the same Alf text as the reference itself. This is because the name must be
resolved during static semantic analysis, but, at that point, the Alf representation of the element being
referenced has not yet been mapped to UML.
In order to handle this in a general way, the Alf abstract syntax uses a generic concept of element
reference. Such a reference may be an external element reference, meaning that it is a reference to a
model element defined in the UML model external to the Alf text. Or it may be an internal element
reference, meaning that it is a reference to the syntax element in the Alf text which will ultimately be
An assignment of a source element that gives the value of a local name, along with a record of the
defined type (if any) and multiplicity of the local name.
Generalizations
None
Synthesized Properties
• lower : Integer
The multiplicity lower bound for the name.
• name : String
The local name for which this is the assigned source.
• source : SyntaxElement
The syntax element that is to be the source for the assigned value of the given local name.
• upper : UnlimitedNatural
The multiplicity upper bound for the local name.
Derived Properties
None
Constraints
None
Helper Operations
None
Generalizations
• SyntaxElement
Synthesized Properties
• documentation : String [*]
The documentation text to be associated with a syntax element. Each string is intended to be mapped
to the body of a comment element in the target UML model.
Derived Properties
None
Constraints
None
Helper Operations
None
12.2.3 ElementReference
A reference to a model element, either directly or via its Alf abstract syntax representation. (NOTE: The
definitions of all the helper operations of ElementReference are specific to its subclasses.)
Generalizations
None
Synthesized Properties
None
Derived Properties
None
Constraints
None
Helper Operations
None
12.2.4 ExternalElementReference
Generalizations
• ElementReference
Derived Properties
None
Constraints
None
Helper Operations
None
12.2.5 InternalElementReference
Generalizations
• ElementReference
Synthesized Properties
• element : SyntaxElement
The Alf syntax element that represents the referenced model element.
Derived Properties
None
Constraints
None
Helper Operations
None
12.2.6 SyntaxElement
A syntax element synthesized in an abstract syntax tree, along with any additional information
determined during static semantic analysis.
Generalizations
None
Synthesized Properties
None
Derived Properties
None
Helper Operations
None
Generalizations
• BinaryExpression
Synthesized Properties
None
Derived Properties
• isConcatenation : Boolean
Whether this is a string concatenation expression.
[2] arithmeticExpressionLowerDerivation
An arithmetic expression has a multiplicity lower bound of 0 if the lower bound if either operand
expression is 0 and 1 otherwise.
[3] arithmeticExpressionOperandTypes
The operands of an arithmetic expression must both have type Integer, unless the operator is +, in which
case they may also both have type String.
[4] arithmeticExpressionTypeDerivation
The type of an arithmetic expression is the same as the type of its operands.
[5] arithmeticExpressionUpperDerivation
An arithmetic expression has a multiplicity upper bound of 1.
Helper Operations
None
13.2.2 AssignmentExpression
Generalizations
• Expression
Synthesized Properties
• leftHandSide : LeftHandSide
The left-hand side of the assignment, to which a value is to be assigned.
• operator : String
The image of the assignment operator used in the expression.
• rightHandSide : Expression
The right-hand side expression of the assignment, which produces the value being assigned.
Derived Properties
• assignment : AssignedSource [0..1]
If the left-hand side is a name, then the new assigned source for that name.
• isArithmetic : Boolean
If this is a compound assignment, whether the compound assignment operator is arithmetic or not.
• isBitStringConversion : Boolean
Whether BitString conversion is required for this assignment.
• isCollectionConversion : Boolean
Whether collection conversion is required for this assignment.
• isDataValueUpdate : Boolean
Whether this assignment updates an attribute of a data value held in a local name or parameter.
• isDefinition : Boolean
Whether this assignment is the definition of a new local name or not.
• isFeature : Boolean
Whether the left-hand side is a feature or not.
• isIndexed : Boolean
If the left-hand side is a feature, whether it has an index or not.
• isSimple : Boolean
Whether this is a simple assignment or not.
Constraints
[1] assignmentExpressionAssignmentDerivation
The new assigned source for an assignment to a local name is the assignment expression. If the
assignment is a definition, then the type is given by the right hand side, the multiplicity upper bound is 1
if the upper bound of the right hand side is 1 and otherwise * and the multiplicity lower bound is 0.
Otherwise, the type and multiplicity are the same as the left hand side.
[2] assignmentExpressionAssignmentsBefore
The assigned source of a name before the right-hand side expression of an assignment expression is the
same as the assigned source before the assignment expression. The assigned source of a name before the
left-hand side is the assigned source after the right-hand side expression.
[4] assignmentExpressionCompoundAssignmentTypeConformance
For a compound assignment, both the left-hand side and the right-hand side must have the same type,
consistent with the arithmetic or logical operator used in the compound assignment operator.
[5] assignmentExpressionExpressionDerivation
For a compound assignment, the effective expression is the left-hand side treated as a name expression,
property access expression or sequence access expression, as appropriate for evaluation to obtain the
original value to be updated.
[6] assignmentExpressionFeatureDerivation
If the left-hand side of an assignment expression is a feature, then the feature of the assignment is the
referent of the left-hand side.
[7] assignmentExpressionIsArithmeticDerivation
An assignment expression is an arithmetic assignment if its operator is a compound assignment operator
for an arithmetic operation.
[8] assignmentExpressionIsBitStringConversionDerivation
An assignment requires BitString conversion if the type of the left-hand side is BitString and either the
type of the right-hand side is Integer or collection conversion is required and the type of the right-hand
side is a collection class whose argument type is Integer.
[9] assignmentExpressionIsCollectionConversionDerivation
An assignment requires collection conversion if the type of the right-hand side is a collection class and
its multiplicity upper bound is 1, and the type of the left-hand side is not a collection class.
[10] assignmentExpressionIsDataValueUpdateDerivation
An assignment expression is a data value update if its left hand side is an attribute of a data value held in
a local name or parameter.
[11] assignmentExpressionIsDefinitionDerivation
An assignment expression is a definition if it is a simple assignment and its left hand side is a local name
for which there is no assignment before the expression.
[12] assignmentExpressionIsFeatureDerivation
The left hand side of an assignment expression is a feature if it is a kind of FeatureLeftHandSide.
[13] assignmentExpressionIsIndexedDerivation
The left hand side of an assignment expression is indexed if it has an index.
[15] assignmentExpressionLowerDerivation
An assignment expression has the same multiplicity lower bound as its right-hand side expression.
[16] assignmentExpressionSimpleAssignmentMultiplicityConformance
If the left-hand side of a simple assignment is not a new local name and the multiplicity upper bound of
the left-hand side is less than or equal to 1, then the multiplicity upper bound of the right-hand side
cannot be greater than that of the left-hand side.
[17] assignmentExpressionSimpleAssignmentTypeConformance
If the left-hand side of a simple assignment is not a new local name, and the right-hand side is not null,
then the left-hand side must either be untyped or have a type that conforms to the type of the right-hand
side expression.
[18] assignmentExpressionTypeDerivation
An assignment expression has the same type as its right-hand side expression.
[19] assignmentExpressionUpperDerivation
An assignment expression has the same multiplicity upper bound as its right-hand side expression.
Helper Operations
[1] updateAssignments ( ) : AssignedSource [*]
The assignments after an assignment expression are the assignments after the left-hand side, updated by
the assignment from the assignment statement, if any.
13.2.3 BehaviorInvocationExpression
Generalizations
• InvocationExpression
Synthesized Properties
• target : QualifiedName
The qualified name of the behavior to be invoked.
Derived Properties
None
[2] behaviorInvocationExpressionFeatureDerivation
If the target qualified name disambiguates to a feature reference, then the feature of a behavior
invocation expression is that feature reference.
[3] behaviorInvocationExpressionReferentConstraint
If the target qualified name does not disambiguate to a feature reference, then it must resolve to a
behavior or an association end. Otherwise it must resolve to a single feature referent according to the
overloading resolution rules, unless it is an implicit destructor call (in which case it has no referent).
[4] behaviorInvocationExpressionReferentDerivation
The referent of a behavior invocation expression is the behavior named by the target or, if the target
disambiguates to a feature reference, the operation or signal being invoked.
Helper Operations
None
13.2.4 BinaryExpression
Generalizations
• Expression
Synthesized Properties
• operand1 : Expression
The expression giving the first operand.
• operand2 : Expression
The expression giving the second operand.
• operator : String
The symbol representing the operator.
Derived Properties
None
[2] binaryExpressionOperandMultiplicity
The operands of a binary expression must both have a multiplicity upper bound of 1.
Helper Operations
[1] updateAssignments ( ) : AssignedSource [*]
The assignments after a binary expression include all the assignments before the expression that are not
reassigned in either operand expression, plus the new assignments from each of the operand expressions.
13.2.5 BitStringUnaryExpression
Generalizations
• UnaryExpression
Synthesized Properties
None
Derived Properties
• isBitStringConversion : Boolean
Whether BitString conversion is required on the operand expression.
Constraints
[1] bitStringUnaryExpresionIsBitStringConversionDerivation
BitString conversion is required if the operand expression of a BitString unary expression has type
Integer.
[2] bitStringUnaryExpressionLowerDerivation
A BitString unary expression has the same multiplicity lower bound as its operand expression.
[3] bitStringUnaryExpressionOperand
The operand expression of a BitString unary expression must have type BitString or Integer and a
multiplicity upper bound of 1.
[5] bitStringUnaryExpressionUpperDerivation
A BitString unary expression has a multiplicity upper bound of 1.
Helper Operations
None
13.2.6 BooleanLiteralExpression
Generalizations
• LiteralExpression
Synthesized Properties
• image : String
The textual image of the literal token for this expression.
Derived Properties
None
Constraints
[1] booleanLiteralExpressionTypeDerivation
The type of a boolean literal expression is Boolean.
Helper Operations
None
13.2.7 BooleanUnaryExpression
Generalizations
• UnaryExpression
Synthesized Properties
None
Derived Properties
None
[2] booleanUnaryExpressionOperand
The operand expression of a Boolean unary expression must have type Boolean and a multiplicity upper
bound of 1.
[3] booleanUnaryExpressionTypeDerivation
A Boolean unary expression has type Boolean.
[4] booleanUnaryExpressionUpperDerivation
A Boolean unary expression has a multiplicity upper bound of 1.
Helper Operations
None
13.2.8 CastExpression
Generalizations
• Expression
Synthesized Properties
• operand : Expression
The operand expression of the cast expression.
Derived Properties
None
Constraints
[1] castExpressionAssignmentsBefore
The assignments before the operand of a cast expression are the same as those before the cast
expression.
[2] castExpressionLowerDerivation
A cast expression has a multiplicity lower bound of 0.
[3] castExpressionTypeDerivation
The type of a cast expression is the referent of the given type name (if there is one).
[5] castExpressionUpperDerivation
A cast expression has a multiplicity upper bound that is the same as the upper bound of its operand
expression.
Helper Operations
[1] updateAssignments ( ) : AssignedSource [*]
The assignments after a cast expression are the same as those after its operand expression.
13.2.9 ClassExtentExpression
Generalizations
• Expression
Synthesized Properties
• className : QualifiedName
The name of the class whose extent is to be obtained.
Derived Properties
None
Constraints
[1] classExtentExpressionExtentType
The given type name must resolve to a non-template class.
[2] classExtentExpressionLowerDerivation
The multiplicity lower bound of a class extent expression is 0.
[3] classExtentExpressionTypeDerivation
The type of a class extent expression is the given class.
[4] classExtentExpressionUpperDerivation
The multiplicity upper bound of a class expression is *.
Helper Operations
None
13.2.10 ClassificationExpression
Generalizations
Synthesized Properties
• typeName : QualifiedName
The name of the type that the operand is to be tested against.
Derived Properties
• isDirect : Boolean
Whether the test is for the operand to have the given type directly or to only conform to the given
type.
• referent : ElementReference
Whether the test is for the operand to have the given type directly or to only conform to the given
type.
Constraints
[1] classificationExpressionIsDirectDerivation
A classification expression is direct if its operator is "hastype".
[2] classificationExpressionLowerDerivation
A classification expression has a multiplicity lower bound that is the same as the lower bound of its
operand expression.
[3] classificationExpressionOperand
The operand expression of a classification expression must have a multiplicity upper bound of 1.
[4] classificationExpressionReferentDerivation
The referent of a classification expression is the classifier to which the type name resolves.
[5] classificationExpressionTypeDerivation
A classification expression has type Boolean.
[6] classificationExpressionTypeName
The type name in a classification expression must resolve to a classifier.
[7] classificationExpressionUpperDerivation
A classification expression has a multiplicity upper bound of 1.
Helper Operations
None
13.2.11 CollectOrIterateExpression
Synthesized Properties
None
Derived Properties
None
Constraints
[1] collectOrIterateExpressionLowerDerivation
A collect or iterate expression has a multiplicity lower bound that is the product of the bounds of its
primary and argument expressions.
[2] collectOrIterateExpressionTypeDerivation
A collect or iterate expression has the same type as its argument expression.
[3] collectOrIterateExpressionUpperDerivation
A collect or iterate expression has a multiplicity upper bound that is the product of the bounds of its
primary and argument expressions.
Helper Operations
None
13.2.12 ConditionalLogicalExpression
A binary expression with a conditional logical expression, for which the evaluation of the second
operand expression is conditioned on the result of evaluating the first operand expression.
Generalizations
• BinaryExpression
Synthesized Properties
None
Derived Properties
None
Constraints
[1] conditionalLogicalExpressionLower
A conditional logical expression has a multiplicity lower bound of 0 if the lower bound if either operand
expression is 0 and 1 otherwise.
[2] conditionalLogicalExpressionOperands
The operands of a conditional logical expression must have type Boolean.
[4] conditionalLogicalExpressionUpper
A conditional logical expression has a multiplicity upper bound of 1.
Helper Operations
[1] updateAssignments ( ) : AssignedSource [*]
If a name has the same assigned source after the second operand expression as before it, then that is its
assigned source after the conditional logical expression. If a name is unassigned before the second
operand expression, then it is considered unassigned after the conditional logical expression, even if it
has an assigned source after the second operand expression. Otherwise its assigned source after the
conditional logical expression is the conditional logical expression itself.
13.2.13 ConditionalTestExpression
An expression that uses the value of one operand expression to condition the evaluation of one of two
other operand expressions.
Generalizations
• Expression
Synthesized Properties
• operand1 : Expression
The first operand expression, which provides the condition to be tested.
• operand2 : Expression
The second operand expression, to be evaluated if the condition is true.
• operand3 : Expression
The third operand expression, to be evaluated if the condition is false.
Derived Properties
None
[2] conditionalTestExpressionAssignmentsBefore
The assignments before the first operand expression of a conditional-test expression are the same as
those before the conditional-test expression. The assignments before the second and third operand
expressions are the same as those after the first operand expression.
[3] conditionalTestExpressionCondition
The first operand expression of a conditional-test expression must be of type Boolean and have a
multiplicity upper bound of 1.
[4] conditionalTestExpressionLowerDerivation
The multiplicity lower bound of a conditional-test operator expression is the minimum of the
multiplicity lower bounds of its second and third operand expressions.
[5] conditionalTestExpressionTypeDerivation
The type of a conditional-test operator expression is the effective common ancestor (if one exists) of the
types of its second and third operand expressions.
[6] conditionalTestExpressionUpperDerivation
The multiplicity upper bound of a conditional-test operator expression is the maximum of the
multiplicity upper bounds of its second and third operand expressions.
Helper Operations
[1] updateAssignments ( ) : AssignedSource [*]
Returns unchanged all assignments for local names that are not reassigned in either the second or third
operand expressions. Any local names that have different assignments after the second and third operand
expressions are adjusted to have the conditional-test expression as their assigned source.
13.2.14 EqualityExpression
Generalizations
• BinaryExpression
Synthesized Properties
None
Derived Properties
• isNegated : Boolean
Constraints
[1] equalityExpressionIsNegatedDerivation
An equality expression is negated if its operator is "!=".
[2] equalityExpressionLowerDerivation
An equality expression has a multiplicity lower bound of 1.
[3] equalityExpressionTypeDerivation
An equality expression has type Boolean.
[4] equalityExpressionUpperDerivation
An equality expression has a multiplicity upper bound of 1.
Helper Operations
None
13.2.15 Expression
NOTE: The derivations for all properties of Expression except AssignmentsAfter are specific to its
various subclasses.
Generalizations
• SyntaxElement
Synthesized Properties
None
Derived Properties
• assignmentAfter : AssignedSource [*]
The assigned sources for local names available lexically after this expression. This includes not only
any assignments made within the expression, but also any assignments that are unchanged from
before the expression.
• lower : Integer
The statically determined lower bound of the multiplicity of this expression.
• upper : UnlimitedNatural
The statically determined upper bound of the multiplicity of this expression.
Constraints
[1] expressionAssignmentsAfterDerivation
The assignments after an expression are given by the result of the updateAssignments helper operation.
[2] expressionUniqueAssignments
No name may be assigned more than once before or after an expression.
Helper Operations
[1] updateAssignments ( ) : AssignedSource [*]
Returns the assignments from before this expression updated for any assignments made in the
expression. By default, this is the same set as the assignments before the expression. This operation is
redefined only in subclasses of Expression for kinds of expressions that make assignments.
13.2.16 ExtentOrExpression
The target of a sequence operation, reduction or expansion expression, which may be either a primary
expression or a class name denoting the class extent.
Generalizations
None
Synthesized Properties
• name : QualifiedName [0..1]
If the target is a qualified name, then that name, before it is disambiguated into either a name
expression or a class name.
Derived Properties
• expression : Expression
The effective expression for the target.
Constraints
[1] extentOrExpressionExpressionDerivation
The effective expression for the target is the parsed primary expression, if the target is not a qualified
name, a name expression, if the target is a qualified name other than a class name, or a class extent
expression, if the target is the qualified name of a class.
13.2.17 FeatureInvocationExpression
Generalizations
• InvocationExpression
Synthesized Properties
• target : FeatureReference [0..1]
A feature reference to the target feature to be invoked.
Derived Properties
None
Constraints
[1] featureInvocationExpressionAlternativeConstructor
An alternative constructor invocation may only occur in an expression statement as the first statement in
the definition for the method of a constructor operation.
[2] featureInvocationExpressionFeatureDerivation
If a feature invocation expression has an explicit target, then that is its feature. Otherwise, it is an
alternative constructor call with its feature determined implicitly.
[3] featureInvocationExpressionImplicitAlternativeConstructor
If there is no target feature expression, then the implicit feature with the same name as the target type
must be a constructor.
[4] featureInvocationExpressionReferentDerivation
If a feature invocation expression is an implicit object destruction, it has no referent. Otherwise, its
referent is the referent of its feature.
[5] featureInvocationExpressionReferentExists
If a feature invocation expression is not an implicit destructor call, then it must be possible to determine
a single valid referent for it according to the overloading resolution rules.
Helper Operations
None
13.2.18 FeatureLeftHandSide
Generalizations
Synthesized Properties
• feature : FeatureReference
The structural feature being assigned.
Derived Properties
None
Constraints
[1] featureLeftHandSideAssignmentAfterDerivation
The assignments after a feature left-hand side are the assignments after the expression of the feature
reference or, if there is an index, those after the index expression.
[2] featureLeftHandSideAssignmentBeforeDerivation
The assignments before the expression of the feature reference of a feature left-hand side are the
assignments before the feature left-hand side.
[3] featureLeftHandSideAssignmentsBefore
If a feature left-hand side has an index, then the assignments before the index expression are the
assignments after the expression of the feature reference.
[4] featureLeftHandSideFeatureExpression
The expression of the feature reference of a feature left-hand side must have a multiplicity upper bound
of 1.
Helper Operations
None
13.2.19 FeatureReference
A reference to a structural or behavioral feature of the type of its target expression or a binary
association end the opposite end of which is typed by the type of its target expression.
Generalizations
• SyntaxElement
Synthesized Properties
• expression : Expression
The target expression.
• nameBinding : NameBinding
The name of the feature.
Derived Properties
• referent : ElementReference [*]
Constraints
[1] featureReferenceReferentDerivation
The features referenced by a feature reference include the features of the type of the target expression
and the association ends of any binary associations whose opposite ends are typed by the type of the
target expression.
[2] featureReferenceTargetType
The target expression of the feature reference may not be untyped, nor may it have a primitive or
enumeration type.
Helper Operations
None
13.2.20 ForAllOrExistsOrOneExpression
Generalizations
• SequenceExpansionExpression
Synthesized Properties
None
Derived Properties
None
Constraints
[1] forAllOrExistOrOneExpressionArgument
The argument of a forAll, exists or one expression must have type Boolean and a multiplicity upper
bound of 1.
[2] forAllOrExistOrOneExpressionLowerDerivation
A forAll, exists or one expression has a multiplicity lower bound of 1.
[3] forAllOrExistOrOneExpressionTypeDerivation
A forAll, exists or one expression has the type Boolean.
[4] forAllOrExistOrOneExpressionUpperDerivation
A forAll, exists or one expression has a multiplicity upper bound of 1.
Helper Operations
None
Generalizations
• Expression
Synthesized Properties
• isPrefix : Boolean = false
Whether the operator is being used as a prefix or a postfix.
• operand : LeftHandSide
The operand, which must have the form of an assignment left-hand side.
Derived Properties
• assignment : AssignedSource [0..1]
If the operand is a name, then the new assigned source for that name.
• expression : Expression
The effective expression used to obtain the original value of the operand to be updated.
• isDataValueUpdate : Boolean
Whether this expression updates an attribute of a data value held in a local name or parameter.
• isFeature : Boolean
Whether the operand is a feature or not.
• isIndexed : Boolean
If the operand is a feature, whether it has an index or not.
Constraints
[1] incrementOrDecrementExpressionAssignment
If the operand of an increment or decrement expression is a name, then the assignment for the
expression is a new assigned source for the name with the expression as the source.
[2] incrementOrDecrementExpressionAssignmentsBefore
The assignments before the operand of an increment or decrement expression are the same as those
before the increment or decrement expression.
[4] incrementOrDecrementExpressionFeature
If the operand of an increment or decrement expression is a feature, then the referent for the operand.
[5] incrementOrDecrementExpressionIsDataValueUpdate
An increment or decrement expression is a data value update if its operand is an attribute of a data value
held in a local name or parameter.
[6] incrementOrDecrementExpressionIsFeatureDerivation
An increment or decrement expression has a feature as its operand if the operand is a kind of
FeatureLeftHandSide.
[7] incrementOrDecrementExpressionIsIndexedDerivation
An increment or decrement expression is indexed if its operand is indexed.
[8] incrementOrDecrementExpressionLowerDerivation
An increment or decrement expression has the same multiplicity lower bound as its operand expression.
[9] incrementOrDecrementExpressionOperand
The operand expression must have type Integer and a multiplicity upper bound of 1.
[10] incrementOrDecrementExpressionTypeDerivation
An increment or decrement expression has type Integer.
[11] incrementOrDecrementExpressionUpperDerivation
An increment or decrement expression has a multiplicity upper bound of 1.
Helper Operations
[1] updateAssignments ( ) : AssignedSource [*]
The assignments after an increment and decrement expression include all those after its operand
expression. Further, if the operand expression, considered as a left hand side, is a local name, then this is
reassigned.
13.2.22 InstanceCreationExpression
Generalizations
• InvocationExpression
Derived Properties
• isConstructorless : Boolean
Whether this is a constructorless object creation expression.
• isObjectCreation : Boolean
Whether this is an object creation expression or a data value creation expression.
Constraints
[1] instanceCreationExpressionConstructor
The constructor name must resolve to a constructor operation (that is compatible with the tuple
argument expressions), a class or a data type, but not both a class and a data type.
[2] instanceCreationExpressionDataTypeCompatibility
If an instance creation expression is a data value creation (not an object creation), then the tuple
argument expressions are matched with the attributes of the named type.
[3] instanceCreationExpressionFeatureDerivation
There is no feature for an instance creation expression.
[4] instanceCreationExpressionIsConstructorlessDerivation
An instance creation expression is constructorless if its referent is a class.
[5] instanceCreationExpressionIsObjectCreationDerivation
An instance creation expression is an object creation if its referent is not a data type.
[6] instanceCreationExpressionReferentDerivation
The referent of an instance creation expression is the constructor operation, class or data type to which
the constructor name resolves.
[7] instanceCreationExpressionTuple
If the expression is constructorless, then its tuple must be empty.
Helper Operations
[1] parameterElements ( ) : ElementReference [*]
Returns the parameters of a constructor operation or the attributes of a data type, or an empty set for a
constructorless instance creation.
Generalizations
• Expression
Synthesized Properties
• tuple : Tuple
The tuple for the invocation expression.
Derived Properties
• feature : FeatureReference [0..1]
For an invocation of a feature, the reference to that feature. This property is set for a feature
invocation expression or for an expression initially parsed as a behavior invocation expression that
disambiguates to a feature invocation expression.
• isAssociationEnd : Boolean
Whether this is an association read or not.
• isBehavior : Boolean
Whether this is a behavior invocation or not.
• isDestructor : Boolean
If this is an operation call, whether the operation is a destructor.
• isImplicit : Boolean
Whether this is an implicit object destruction.
• isOperation : Boolean
Whether this is an operation call or not.
• isSignal : Boolean
Whether this is a signal send or not.
[2] invocationExpressionIsAssociationEndDerivation
An invocation expression is an association end read if its referent is an association end.
[3] invocationExpressionIsBehaviorDerivation
An invocation expression is a behavior invocation if its referent is a behavior.
[4] invocationExpressionIsDestructorDerivation
An invocation expression is a destructor call either implicitly or if it is an explicit operation call to a
destructor operation.
[5] invocationExpressionIsImplicitDerivation
An invocation expression is an implicit object destruction if it has a feature with the name "destroy" and
no explicit referents.
[6] invocationExpressionIsOperationDerivation
An invocation expression is an operation call if its referent is an operation.
[7] invocationExpressionIsSignalDerivation
An invocation expression is a signal send if its referent is a signal.
[8] invocationExpressionLowerDerivation
The multiplicity lower bound of an invocation expression is determined by the return parameter (if any)
of the referent.
[9] invocationExpressionParameterDerivation
The parameters of an invocation expression are given by the result of the parameterElements helper
operation.
[10] invocationExpressionTypeDerivation
The type of an invocation expression is determined by the return parameter (if any) of the referent.
[11] invocationExpressionUpperDerivation
The multiplicity upper bound of an invocation expression is determined by the return parameter (if any)
of the referent.
Helper Operations
[1] parameterElements ( ) : ElementReference [*]
Returns references to the elements that act as the parameters of the referent. For a behavior or operation,
these are the owned parameters, in order. Otherwise (by default), they are actually any properties of the
13.2.24 IsolationExpression
Generalizations
• UnaryExpression
Synthesized Properties
None
Derived Properties
None
Constraints
[1] isolationExpressionLowerDerivation
An isolation expression has the multiplicity lower bound of its operand expression.
[2] isolationExpressionTypeDerivation
An isolation expression has the type of its operand expression.
[3] isolationExpressionUpperDerivation
An isolation expression has the multiplicity upper bound of its operand expression.
Helper Operations
None
13.2.25 IsUniqueExpression
Generalizations
• SequenceExpansionExpression
Synthesized Properties
None
Derived Properties
None
[2] isUniqueExpressionLowerDerivation
An isUnique expression has a multiplicity lower bound of 1.
[3] isUniqueExpressionTypeDerivation
An isUnique expression has the type Boolean.
[4] isUniqueExpressionUpperDerivation
An isUnique expression has a multiplicity upper bound of 1.
Helper Operations
None
13.2.26 LeftHandSide
NOTE: The derivations for the derived properties of LeftHandSide are specific to its various subclasses.
Generalizations
• SyntaxElement
Synthesized Properties
• index : Expression [0..1]
An optional expression that evaluates to an index into the values of an ordered sequence.
Derived Properties
• assignmentAfter : AssignedSource [*]
The assignments after the left-hand side.
Constraints
[1] leftHandSideIndexExpression
If a left-hand side has an index, then the index expression must have a multiplicity upper bound no
greater than 1.
Helper Operations
None
Generalizations
• InvocationExpression
Synthesized Properties
• associationName : QualifiedName
The qualified name of the association whose links are being acted on.
• operation : String
The name of the link operation.
Derived Properties
• isClear : Boolean
Whether the operation is clearing the association.
• isCreation : Boolean
Whether the operation is for link creation.
Constraints
[1] linkOperationExpressionArgumentCompatibility
Each argument expression must be assignable to its corresponding expression.
[2] linkOperationExpressionAssociationReference
The qualified name of a link operation expression must resolve to a single association.
[3] linkOperationExpressionFeatureDerivation
There is no feature for a link operation expression.
[4] linkOperationExpressionIsClearDerivation
A link operation expression is for clearing an association if the operation is "clearAssoc".
[5] linkOperationExpressionIsCreationDerivation
A link operation expression is for link creation if its operation is "createLink".
[6] linkOperationExpressionReferentDerivation
The referent for a link operation expression is the named association.
Helper Operations
[1] parameterElements ( ) : ElementReference [*]
For a clear association operation, returns a single, typeless parameter. Otherwise, returns the ends of the
named association.
Generalizations
• Expression
Synthesized Properties
None
Derived Properties
None
Constraints
[1] literalExpressionLowerDerivation
The multiplicity lower bound of a literal expression is always 1.
[2] literalExpressionTypeDerivation
The type of a literal expression is given by the type of the literal, as defined for each subclass below.
[3] literalExpressionUpperDerivation
The multiplicity upper bound of a literal expression is always 1.
Helper Operations
None
13.2.29 LogicalExpression
Generalizations
• BinaryExpression
Synthesized Properties
None
Derived Properties
• isBitStringConversion1 : Boolean
Whether the first operand expression requires BitString conversion.
• isBitStringConversion2 : Boolean
Whether the second operand expression requires BitString conversion.
• isBitWise : Boolean
Whether this is a bit-wise logical operation on bit strings.
[2] logicalExpressionIsBitStringConversion2Derivation
BitString conversion is required if the second operand expression of a shift expression has type Integer.
[3] logicalExpressionIsBitWiseDerivation
A logical expression is bit-wise if the type of its first operand is not Boolean.
[4] logicalExpressionLowerDerivation
A logical expression has a multiplicity lower bound of 0 if the lower bound if either operand expression
is 0 and 1 otherwise.
[5] logicalExpressionOperands
The operands of a logical expression must have type Boolean.
[6] logicalExpressionTypeDerivation
A logical expression has type Boolean.
[7] logicalExpressionUpperDerivation
A logical expression has a multiplicity upper bound of 1.
Helper Operations
None
13.2.30 NameBinding
Generalizations
• SyntaxElement
Synthesized Properties
• binding : TemplateBinding [0..1]
The template binding to be used, if the name denotes a template.
• name : String
An unqualified name. For names that appeared as unrestricted names in the input text, the string
value here excludes the surrounding single quote characters and has any escape sequences resolved
to the denoted special characters.
Derived Properties
None
Helper Operations
None
13.2.31 NamedExpression
Generalizations
• SyntaxElement
Synthesized Properties
• expression : Expression
The argument expression.
• name : String
The parameter name.
Derived Properties
• isBitStringConverstion : Boolean
Whether the argument expression requires bit string conversion.
• isCollectionConversion : Boolean
Whether the argument expression requires collection conversion.
Constraints
[1] namedExpressionIsBitStringConversionDerivation
Bit string conversion is required if the type of the type of the corresponding parameter is BitString, or a
collection class instantiated with a BitString type, and the type of the argument expression is not
BitString.
[2] namedExpressionIsCollectionConversionDerivation
Collection conversion is required if the type of the corresponding parameter is a collection class and the
type of the argument expression is not.
Helper Operations
None
A template binding in which the arguments are matched to formal template parameters by name.
Generalizations
• TemplateBinding
Synthesized Properties
• substitution : TemplateParameterSubstitution [1..*]
The substitutions of arguments for template parameters.
Derived Properties
None
Constraints
None
Helper Operations
None
13.2.33 NamedTuple
Generalizations
• Tuple
Synthesized Properties
• namedExpression : NamedExpression [*]
The argument expressions for this tuple paired with the corresponding parameter names.
Derived Properties
None
Constraints
None
Helper Operations
None
13.2.34 NameExpression
Generalizations
• Expression
Derived Properties
• assignment : AssignedSource [0..1]
The assigned source for the referenced name, if the name is a local or parameter name.
Constraints
[1] nameExpressionAssignmentDerivation
If the name in a name expression is a local or parameter name, then its assignment is its assigned source
before the expression.
[2] nameExpressionEnumerationLiteralDerivation
If the name in a name expression resolves to an enumeration literal name, then that is the enumeration
literal for the expression.
[3] nameExpressionLowerDerivation
The multiplicity lower bound of a name expression is determined by its name.
[4] nameExpressionPropertyAccessDerivation
If the name in a name expression disambiguates to a feature reference, then the equivalent property
access expression has the disambiguation of the name as its feature. The assignments before the property
access expression are the same as those before the name expression.
[5] nameExpressionResolution
If the name referenced by this expression is not a disambiguated feature reference or a local or
parameter name, then it must resolve to exactly one enumeration literal.
[6] nameExpressionTypeDerivation
The type of a name expression is determined by its name. If the name is a local name or parameter with
an assignment, then the type of the name expression is the type of that assignment. If the name is an
enumeration literal, then the type of the name expression is the corresponding enumeration. If the name
disambiguates to a feature reference, then the type of the name expression is the type of the equivalent
property access expression.
13.2.35 NameLeftHandSide
Generalizations
• LeftHandSide
Synthesized Properties
• target : QualifiedName
The name that is the target of the assignment.
Derived Properties
None
Constraints
[1] nameLeftHandSideAssignmentAfterDerivation
The assignments after a name left-hand side are the same as the assignments before.
[2] nameLeftHandSideAssignmentsBefore
If a name left-hand side has an index, then the target name must already have an assigned source and the
assignments before the index expression are the assignments before the left-hand side.
[3] nameLeftHandSideTargetAssignment
The target of a name left hand side may not already have an assigned source that is a loop variable
definition, an annotation, a sequence expansion expression or a parameter that is an in parameter.
Helper Operations
None
13.2.36 NaturalLiteralExpression
Generalizations
• LiteralExpression
Synthesized Properties
• image : String
The textual image of the literal token for this expression.
Constraints
[1] naturalLiteralExpressionTypeDerivation
The type of a natural literal is the Alf library type Natural.
NOTE: If the context of a natural literal expression unambiguously requires either an Integer or an
UnlimitedNatural value, then the result of the literal expression is implicitly downcast to the required
type. If the context is ambiguous, however, than an explicit cast to Integer or UnlimitedNatural must be
used.
Helper Operations
None
13.2.37 NumericUnaryExpression
Generalizations
• UnaryExpression
Synthesized Properties
None
Derived Properties
None
Constraints
[1] numericUnaryExpressionLowerDerivation
A numeric unary expression has the same multiplicity lower bound as its operand expression.
[2] numericUnaryExpressionOperand
The operand expression must have type Integer and a multiplicity upper bound of 1.
[3] numericUnaryExpressionTypeDerivation
A numeric unary expression must have type Integer.
[4] numericUnaryExpressionUpperDerivation
A numeric unary expression has a multiplicity upper bound of 1.
Helper Operations
None
Generalizations
• NamedExpression
Synthesized Properties
None
Derived Properties
• leftHandSide : LeftHandSide
The argument expression considered as an assignment left-hand side.
Constraints
[1] outputNamedExpressionForm
The argument for an output parameter must be either be null, a name expression, a property access
expression, or a sequence access expression whose primary expression is a name expression or a
property access expression.
[2] outputNamedExpressionLeftHandSideDerivation
The equivalent left-hand side for an output named expression depends on the kind of expression. If the
expression is a name expression with no disambiguation, then the left-hand side is a name left-hand side
with the name from the name expression. If the expression is a name expression that disambiguates to a
feature reference, then the left-hand side is a feature left-hand side for that feature reference. If the
expression is a property access expression, then the left-hand side is a feature left-hand side for the
feature reference of the property access expression. If the expression is a sequence access expression,
then the left-hand side is a name left-hand side or feature left-hand side, as above, depending on whether
the primary expression of the sequence access expression is a name expression or property access
expression, and an index given by the index expression of the sequence access expression. Otherwise the
left-hand side is empty.
Helper Operations
None
13.2.39 PositionalTemplateBinding
A template binding in which the arguments are matched to formal template parameters in order by
position.
Generalizations
• TemplateBinding
Synthesized Properties
• argumentName : QualifiedName [1..*]
The arguments for this template binding, to be matched by position to the template parameters.
Constraints
None
Helper Operations
None
13.2.40 PositionalTuple
Generalizations
• Tuple
Synthesized Properties
• expression : Expression [*]
The argument expressions for this tuple, to be matched by position to the invocation parameters.
Derived Properties
None
Constraints
None
Helper Operations
None
13.2.41 PropertyAccessExpression
Generalizations
• Expression
Synthesized Properties
• featureReference : FeatureReference
A reference to a structural feature.
Derived Properties
• feature : ElementReference
The referenced structural feature.
[2] propertyAccessExpressionFeatureDerivation
The feature of a property access expression is the structural feature to which its feature reference
resolves.
[3] propertyAccessExpressionFeatureResolution
The feature reference for a property access expression must resolve to a single structural feature.
[4] propertyAccessExpressionLowerDerivation
The multiplicity upper bound of a property access expression is given by the product of the multiplicity
upper bounds of the referenced feature and the target expression.
[5] propertyAccessExpressionTypeDerivation
The type of a property access expression is the type of the referenced feature.
[6] propertyAccessExpressionUpperDerivation
The multiplicity upper bound of a property access expression is given by the product of the multiplicity
upper bounds of the referenced feature and the target expression.
Helper Operations
[1] updateAssignments ( ) : AssignedSource [*]
The assignments after a property access expression are the same as those after the target expression of
its feature reference.
13.2.42 QualifiedName
Generalizations
• SyntaxElement
Synthesized Properties
• isAmbiguous : Boolean = false
Whether this qualified name is ambiguous.
Derived Properties
• disambiguation : FeatureReference [0..1]
• isFeatureReference : Boolean
Indicates whether this qualified name has been disambiguated to a feature reference.
• pathName : String
The complete path name for the qualified name, with individual name bindings separated by "::"
punctuation.
• unqualifiedName : NameBinding
The rightmost individual name binding in the qualified name, without the qualification.
Constraints
[1] qualifiedNameDisambiguationDerivation
If a qualified name is not ambiguous or it resolves to a namespace, then it is has no disambiguation.
Otherwise, its disambiguation is a feature reference with a name given by the unqualified name of the
qualified name and a target expression determined by the disambiguation of the qualification of the
qualified name.
[2] qualifiedNameIsFeatureReferenceDerivation
A qualified name is a feature reference is its disambiguation is not empty.
[3] qualifiedNameLocalName
If a qualified name is a local name, then the reference must be within the same local scope as the
definition of the named element.
[4] qualifiedNameNonLocalUnqualifiedName
If a qualified name is an unqualified, non-local name, then it must be visible in the current scope of the
use of the name.
[6] qualifiedNameQualificationDerivation
The qualification of a qualified name is a empty if the qualified name has only one name binding.
Otherwise it is the qualified name consisting of all the name bindings of the original qualified name
except for the last one. The qualification of a qualified name is considered ambiguous if the qualified
name is ambiguous and has more than two name bindings.
[7] qualifiedNameQualifiedResolution
If a qualified name has a qualification, then its unqualified name must name an element of the
namespace named by the qualification, where the first name in the qualification must name an element
of the current scope.
[8] qualifiedNameReferentDerivation
The referents of a qualified name are the elements to which the name may resolve in the current scope,
according to the UML rules for namespaces and named elements.
[9] qualifiedNameTemplateBinding
If the unqualified name of a qualified name has a template binding, then the template name must resolve
to a template. The template binding must have an argument name for each of the template parameters
and each argument name must resolve to a classifier. If the template parameter has constraining
classifiers, then the referent of the corresponding argument name must conform to all those constraining
classifiers.
[10] qualifiedNameTemplateNameDerivation
If the last name binding in a qualified name has a template binding, then the template name is a qualified
name with the same template bindings as the original qualified name, but with the template binding
removed on the last name binding.
[11] qualifiedNameUnqualifiedNameDerivation
The unqualified name of a qualified name is the last name binding.
Helper Operations
None
Generalizations
• BinaryExpression
Synthesized Properties
None
Derived Properties
• isUnlimitedNatural : Boolean
Whether this is an UnlimitedNatural comparison.
Constraints
[1] relationalExpressionIsLowerDerivation
A relational expression has a multiplicity lower bound of 0 if the lower bound if either operand
expression is 0 and 1 otherwise.
[2] relationalExpressionIsTypeDerivation
The type of a relational expression is Boolean.
[3] relationalExpressionIsUnlimitedNaturalDerivation
A relational expression is an UnlimitedNatural comparison if either one of its operands has type
UnlimitedNatural.
[4] relationalExpressionIsUpperDerivation
A relational expression has a multiplicity upper bound of 1.
[5] relationalExpressionOperandTypes
The operand expressions for a comparison operator must have type Integer, UnlimitedNatural or
Natural. However, it is not allowed to have one operand expression be Integer and the other be
UnlimitedNatural.
Helper Operations
None
13.2.44 SelectOrRejectExpression
Generalizations
• SequenceExpansionExpression
Synthesized Properties
None
Constraints
[1] selectOrRejectExpressionArgument
The argument of a select or reject expression must have type Boolean and a multiplicity upper bound of
1.
[2] selectOrRejectExpressionLowerDerivation
A select or reject expression has a multiplicity lower bound of 0.
[3] selectOrRejectExpressionTypeDerivation
A select or reject expression has the same type as its primary expression.
[4] selectOrRejectExpressionUpperDerivation
A select or reject expression has a multiplicity upper bound of *.
Helper Operations
None
13.2.45 SequenceAccessExpression
Generalizations
• Expression
Synthesized Properties
• index : Expression
The expression whose value is the index of the element being accessed in the sequence.
• primary : Expression
The expression whose value is the sequence being accessed.
Derived Properties
None
Constraints
[1] sequenceAccessExpressionIndexMultiplicity
The multiplicity upper bound of the index of a sequence access expression must be 1.
[2] sequenceAccessExpressionIndexType
The type of the index of a sequence access expression must be Integer.
[4] sequenceAccessExpressionTypeDerivation
The type of a sequence access expression is the same as the type of its primary expression.
[5] sequenceAccessExpressionUpperDerivation
The multiplicity upper bound of a sequence access expression is 1.
Helper Operations
None
13.2.46 SequenceConstructionExpression
Generalizations
• Expression
Synthesized Properties
• elements : SequenceElements [0..1]
The specification of the elements in the sequence.
Derived Properties
None
Constraints
[1] sequenceConstructionExpressionLowerDerivation
If a sequence construction expression has multiplicity, then its multiplicity lower bound is given by its
elements, if this is not empty, and zero otherwise. If a sequence construction expression does not have
multiplicity, then its multiplicity lower bound is one.
[2] sequenceConstructionExpressionType
The type name of a sequence construction expression must resolve to a non-template classifier. If the
expression does not have multiplicity, then this classifier must be the instantiation of a collection class.
[3] sequenceConstructionExpressionTypeDerivation
The type of a sequence construction expression is the named type.
Helper Operations
None
13.2.47 SequenceElements
Generalizations
• SyntaxElement
Synthesized Properties
None
Derived Properties
• lower : Integer
The multiplicity lower bound of the elements of the sequence. The derivation for this property is
given in the subclasses of SequenceElements.
• upper : UnlimitedNatural
The multiplicity upper bound of the elements of the sequence. The derivation for this property is
given in the subclasses of SequenceElements.
Constraints
None
Helper Operations
None
13.2.48 SequenceExpansionExpression
An expression used to carry out one of a predefined set of operations over each of the elements in a
sequence.
Generalizations
• Expression
Synthesized Properties
• argument : Expression
The argument expression. The exact form required for this expression depends on which expansion
operation is being carried out.
• operation : String
• primary : ExtentOrExpression
The class name or primary expression that evaluates to the sequence to be acted on.
• variable : String
The name of the expansion variable available as a local name within the argument expression.
Derived Properties
• variableSource : AssignedSource
The assigned source for the expansion variable within the argument expression. The source is
actually the sequence expansion expression itself.
Constraints
[1] sequenceExpansionExpressionAssignmentsBeforeArgument
The assignments before the argument expression of a sequence expansion expression include those after
the primary expression plus one for the expansion variable.
[2] sequenceExpansionExpressionAssignmentsBeforePrimary
The assignments before the primary expression of a sequence expansion expression are the same as the
assignments before the sequence expansion expression.
[3] sequenceExpansionExpressionVariableAssignment
The expansion variable may not be assigned within the argument expression.
[4] sequenceExpansionExpressionVariableName
The expansion variable name may not conflict with any name already assigned after the primary
expression.
[5] sequenceExpansionExpressionVariableSourceDerivation
The assigned source for the expansion variable of a sequence expansion expression is the expression
itself.
Helper Operations
[1] updateAssignments ( ) : AssignedSource [*]
The assignments after a sequence expansion expression are the same as after its primary expression.
13.2.49 SequenceExpressionList
Generalizations
• SequenceElements
Derived Properties
None
Constraints
[1] sequenceExpressionListLowerDerivation
The multiplicity lower bound of the elements of a sequence expression list is given by the sum of the
lower bounds of each of the expressions in the list.
[2] sequenceExpressionListUpperDerivation
The multiplicity lower bound of the elements of a sequence expression list is given by the sum of the
lower bounds of each of the expressions in the list. If any of the expressions in the list have an
unbounded upper bound, then the sequence expression list also has an unbounded upper bound.
Helper Operations
None
13.2.50 SequenceOperationExpression
Generalizations
• InvocationExpression
Synthesized Properties
• operation : QualifiedName [0..1]
The qualified name of the behavior being invoked.
• primary : ExtentOrExpression
The expression or class name whose value is gives the sequence to be operated on.
Derived Properties
• isBitStringConversion : Boolean
Whether type primary expression requires BitString conversion.
• isCollectionConversion : Boolean
Whether the primary expression requires collection conversion.
Constraints
[1] sequenceOperationExpressionArgumentCompatibility
The type of an input argument expression of a sequence operation parameter must be assignable to its
corresponding parameter. The type of an output parameter must be assignable to its corresponding
[2] sequenceOperationExpressionAssignmentsBefore
The assignments before the primary expression of a sequence operation expression are the same as the
assignments before the sequence operation expression.
[3] sequenceOperationExpressionFeatureDerivation
There is no feature for a sequence operation expression.
[4] sequenceOperationExpressionIsBitStringConversionDerivation
BitString conversion is required if type of the first parameter of the referent of a sequence operation
expression is BitString and either the type of its primary expression is Integer or collection conversion is
required and the type of its primary expression is a collection class whose argument type is Integer.
[5] sequenceOperationExpressionIsCollectionConversionDerivation
Collection conversion is required if the type of the primary expression of a sequence operation
expression is a collection class.
[6] sequenceOperationExpressionOperationReferent
There must be a single behavior that is a resolution of the operation qualified name of a sequence
operation expression with a least one parameter, whose first parameter has direction in or inout, has
multiplicity [0..*] and to which the target primary expression is assignable.
[7] sequenceOperationExpressionReferentDerivation
The referent for a sequence operation expression is the behavior named by the operation for the
expression.
[8] sequenceOperationExpressionTargetCompatibility
If the first parameter of the referent has direction inout, then the parameter type must have the same type
as the primary expression.
Helper Operations
[1] updateAssignments ( ) : AssignedSource [*]
The assignments after a sequence operation expression include those made in the primary expression
and those made in the tuple and, for an "in place" operation (one whose first parameter is inout), that
made by the sequence operation expression itself.
13.2.51 SequenceRange
Generalizations
• SequenceElements
• rangeUpper : Expression
The expression whose value gives the upper bound for the range.
Derived Properties
None
Constraints
[1] sequenceRangeLowerDerivation
The multiplicity lower bound of a sequence range is 0.
[2] sequenceRangeUpperDerivation
The multiplicity uper bound of a sequence range is * (since it is not possible, in general, to statically
determine a more constrained upper bound).
Helper Operations
None
13.2.52 SequenceReductionExpression
An expression used to reduce a sequence of values effectively by inserting a binary operation between
the values.
Generalizations
• Expression
Synthesized Properties
• behaviorName : QualifiedName
The name of the behavior to be used as the reducer.
• primary : ExtentOrExpression
The target class name or primary expression for the reduction.
Derived Properties
• referent : ElementReference
A reference to the behavior to be used as the reducer.
[2] sequenceReductionExpressionBehavior
The behavior name in a sequence reduction expression must denote a behavior.
[3] sequenceReductionExpressionBehaviorParameters
The referent behavior must have two in parameters, a return parameter and no other parameters. The
parameters must all have the same type as the argument expression and multiplicity [1..1].
[4] sequenceReductionExpressionLowerDerivation
A sequence reduction expression has a multiplicity lower bound of 1.
[5] sequenceReductionExpressionReferentDerivation
The referent for a sequence reduction expression is the behavior denoted by the behavior name of the
expression.
[6] sequenceReductionExpressionTypeDerivation
A sequence reduction expression has the same type as its primary expression.
[7] sequenceReductionExpressionUpperDerivation
A sequence reduction expression has a multiplicity upper bound of 1.
Helper Operations
[1] updateAssignments ( ) : AssignedSource [*]
The assignments after a sequence reduction expression are the same as after its primary expression.
13.2.53 ShiftExpression
Generalizations
• BinaryExpression
Synthesized Properties
None
Derived Properties
• isBitStringConversion : Boolean
Whether the first operand expression requires BitString conversion.
[2] shiftExpressionLowerDerivation
A shift expression has a multiplicity lower bound of 0 if the lower bound if either operand expression is
0 and 1 otherwise.
[3] shiftExpressionOperands
The operands of a shift expression must have type BitString or Integer.
[4] shiftExpressionTypeDerivation
A shift expression has type BitString.
[5] shiftExpressionUpperDerivation
A shift expression has a multiplicity upper bound of 1.
Helper Operations
None
13.2.54 StringLiteralExpression
Generalizations
• LiteralExpression
Synthesized Properties
• image : String
The textual image of the literal token for this expression, with quote characters removed and escaped
sequences resolved to the denoted special character.
Derived Properties
None
Constraints
[1] stringLiteralExpressionTypeDerivation
The type of a string literal expression is String.
Helper Operations
None
13.2.55 SuperInvocationExpression
Synthesized Properties
• target : QualifiedName [0..1]
The name of the operation to be invoked, optionally qualified with the name of the appropriate
superclass.
Derived Properties
None
Constraints
[1] superInvocationExpressionConstructorCall
If the referent is the method of a constructor operation, the super invocation expression must occur in an
expression statement at the start of the definition for the method of a constructor operation, such that any
statements preceding it are also super constructor invocations.
[2] superInvocationExpressionDestructorCall
If the referent is the method of a destructor operation, the super invocation expression must occur in an
within the method of a destructor operation.
[3] superInvocationExpressionFeatureDerivation
There is no feature for a super invocation.
[4] superInvocationExpressionImplicitTarget
If the target is empty, the referent must be the method for a constructor operation.
[5] superInvocationExpressionOperation
It must be possible to identify a single valid operation denoted by the target of a super invocation
expression that satisfies the overloading resolution rules.
[6] superInvocationExpressionQualification
If the target has a qualification, then this must resolve to one of the superclasses of the current context
class.
[7] superInvocationExpressionReferentDerivation
The referent of a super invocation expression is the method behavior of the operation identified using
the overloading resolution rules.
Helper Operations
None
13.2.56 TemplateBinding
A list of type names used to provide arguments for the parameters of a template.
Synthesized Properties
None
Derived Properties
None
Constraints
None
Helper Operations
None
13.2.57 TemplateParameterSubstitution
Generalizations
• SyntaxElement
Synthesized Properties
• argumentName : QualifiedName
The name of the argument type.
• parameterName : String
The name of the template parameter.
Derived Properties
None
Constraints
None
Helper Operations
None
13.2.58 ThisExpression
Generalizations
• Expression
Synthesized Properties
None
Constraints
[1] thisExpressionLowerDerivation
The multiplicity lower bound of a this expression is always 1.
[2] thisExpressionTypeDerivation
The static type of a this expression is the statically determined context classifier for the context in which
the this expression occurs.
[3] thisExpressionUpperDerivation
The multiplicity upper bound of a this expression is always 1.
Helper Operations
None
13.2.59 Tuple
Generalizations
• SyntaxElement
Synthesized Properties
• invocation : InvocationExpression
The invocation expression of which this tuple is a part.
Derived Properties
• input : NamedExpression [*]
The argument expressions from this tuple, matched to the input parameters (direction in and inout)
of the invocation. An empty sequence construction expression is included for any input parameter
that is not explicitly matched in the tuple.
Constraints
[1] tupleAssignmentsAfter
A name may be assigned in at most one argument expression of a tuple.
[3] tupleInputDerivation
A tuple has the same number of inputs as its invocation has input parameters. For each input parameter,
the tuple has a corresponding input with the same name as the parameter and an expression that is the
matching argument from the tuple, or an empty sequence construction expression if there is no matching
argument.
[4] tupleNullInputs
An input parameter may only have a null argument if it has a multiplicity lower bound of 0.
[5] tupleOutputDerivation
A tuple has the same number of outputs as its invocation has output parameters. For each output
parameter, the tuple has a corresponding output with the same name as the parameter and an expression
that is the matching argument from the tuple, or an empty sequence construction expression if there is no
matching argument.
[6] tupleOutputs
An output parameter may only have a null argument if it is an out parameter.
Helper Operations
None
13.2.60 UnaryExpression
Generalizations
• Expression
Synthesized Properties
• operand : Expression
The expression giving the operand.
• operator : String
The symbol representing the operator.
Derived Properties
None
Helper Operations
[1] updateAssignments ( ) : AssignedSource [*]
By default, the assignments after a unary expression are the same as those after its operand expression.
13.2.61 UnboundedLiteralExpression
Generalizations
• LiteralExpression
Synthesized Properties
None
Derived Properties
None
Constraints
[1] unboundedLiteralExpressionDerivation
The type of an unbounded literal expression is UnlimitedNatural.
Helper Operations
None
Generalizations
• SyntaxElement
Synthesized Properties
• block : Block [0..1]
The body of the accept block, executed if one of the named signals is received.
• signalNames : QualifiedNameList
A list of names of the signals accepted by this accept block.
Derived Properties
• signal : ElementReference [1..*]
Constraints
[1] acceptBlockSignalDerivation
The signals of an accept block are the referents of the signal names of the accept block.
[2] acceptBlockSignalNames
All signal names in an accept block must resolve to signals.
Helper Operations
None
14.2.2 AcceptStatement
Generalizations
• Statement
Synthesized Properties
• acceptBlock : AcceptBlock [1..*]
One or more blocks for accepting alternate groups of signals.
Derived Properties
• behavior : ElementReference
The behavior containing the accept statement.
• isSimple : Boolean
Whether the accept statement is simple or not.
Constraints
[1] acceptStatementAssignmentsAfter
If a name is assigned in any block of an accept statement, then the assigned source of the name after the
accept statement is the accept statement itself.
[2] acceptStatementAssignmentsBefore
The assignments before any block of an accept statement are the assignments before the accept
statement.
[3] acceptStatementCompoundAcceptLocalName
For a compound accept statement, a local name defined in an accept block has the accept block as its
assigned source before the block associated with the accept block. The type of the local name is the
effective common ancestor of the specified signals for that accept clause, if one exists, and it is untyped
otherwise. However, the local name is considered unassigned after the accept statement.
[5] acceptStatementEnclosedStatements
The enclosing statement for all statements in the blocks of all accept blocks of an accept statement is the
accept statement.
[6] acceptStatementIsSimpleDerivation
An accept statement is simple if it has exactly one accept block and that accept block does not have a
block.
[7] acceptStatementNames
Any name defined in an accept block of an accept statement must be unassigned before the accept
statement.
[8] acceptStatementNewAssignments
If a name is unassigned before an accept statement and assigned in any block of an accept statement,
then it must be assigned in every block.
[9] acceptStatementSignals
The containing behavior of an accept statement must have receptions for all signals from all accept
blocks of the accept statement. No signal may be referenced in more than one accept block of an accept
statement.
[10] acceptStatementSimpleAcceptLocalName
A local name specified in the accept block of a simple accept statement has the accept statement as its
assigned source after the accept statement. The type of the local name is the effective common ancestor
of the specified signals, if one exists, and it is untyped otherwise.
Helper Operations
None
14.2.3 Annotation
Generalizations
• SyntaxElement
Synthesized Properties
• argument : String [*]
If permitted by the annotation, an optional list of local names relevant to the annotation.
• identifier : String
Derived Properties
None
Constraints
None
Helper Operations
None
14.2.4 Block
Generalizations
• SyntaxElement
Synthesized Properties
• statement : Statement [*]
The ordered sequence of statements in the block.
Derived Properties
• assignmentAfter : AssignedSource [*]
The assigned sources for local names available lexically after this block. This includes not only any
assignments made within the statement, but also any assignments that are unchanged from before the
statement.
Constraints
[1] blockAssignmentAfterDerivation
If a block is not empty, then the assignments after the block are the same as the assignments after the
last statement of the block. Otherwise they are the same as the assignments before the block.
[2] blockAssignmentsBefore
[3] blockAssignmentsBeforeStatements
The assignments before each statement in a block other than the first are the same as the assignments
after the previous statement.
Helper Operations
None
Generalizations
• Statement
Synthesized Properties
• block : Block
The block to be executed.
Derived Properties
• isParallel : Boolean
Whether the statements in the block of this block statement should be executed concurrently.
Constraints
[1] blockStatementAssignmentsAfter
The assignments after a block statement are the same as the assignments after the block of the block
statement.
[2] blockStatementAssignmentsBefore
The assignments before the block of a block statement are the same as the assignments before the block
statement.
[3] blockStatementEnclosedStatements
The enclosing statement for all the statements in the block of a block statement is the block statement.
[4] blockStatementIsParallelDerivation
A block statement is parallel if it has a @parallel annotation.
[5] blockStatementParallelAssignments
In a parallel block statement, any name assigned in one statement of the block may not be further
assigned in any subsequent statement in the same block.
Helper Operations
[1] annotationAllowed ( in annotation : Annotation ) : Boolean
In addition to an @isolated annotation, a block statement may have a @parallel annotation. It may not
have any arguments.
14.2.6 BreakStatement
Generalizations
• Statement
Derived Properties
• target : Statement
The enclosing statement that is terminated by this break statement.
Constraints
[1] breakStatementNonparallelTarget
The target of a break statement may not have a @parallel annotation.
[2] breakStatementTargetDerivation
The target of a break statement is the innermost switch, while, do or for statement enclosing the break
statement.
Helper Operations
[1] annotationAllowed ( in annotation : Annotation ) : Boolean
A break statement may not have any annotations.
14.2.7 ClassifyStatement
Generalizations
• Statement
Synthesized Properties
• expression : Expression
The expression to be evaluated to obtain the object to be reclassified.
Derived Properties
• fromClass : ElementReference [*]
The classes denoted by the names in the from list.
Constraints
[1] classifyStatementAssignmentsAfter
The assignments after a classify statement are the same as the assignments after its expression.
[2] classifyStatementAssignmentsBefore
The assignments before the expression of a classify statement are the same as the assignments before the
statement.
[3] classifyStatementClasses
All the from and to classes of a classify statement must be subclasses of the type of the target expression
and none of them may have a common superclass that is a subclass of the type of the target expression
(that is, they must be disjoint subclasses).
[4] classifyStatementClassNames
All qualified names listed in the from or to lists of a classify statement must resolve to classes.
[5] classifyStatementExpression
The expression in a classify statement must have a class as its type and multiplicity upper bound of 1.
[6] classifyStatementFromClassDerivation
The from classes of a classify statement are the class referents of the qualified names in the from list for
the statement.
[7] classifyStatementToClassDerivation
The to classes of a classify statement are the class referents of the qualified names in the to list for the
statement.
Helper Operations
None
14.2.8 ConcurrentClauses
Generalizations
• SyntaxElement
Synthesized Properties
• clause : NonFinalClause [1..*]
The conditional clauses in the group.
Derived Properties
None
[2] concurrentClausesConditionAssignments
The same name may not be assigned in more than one conditional expression within the same
concurrent set of clauses.
Helper Operations
None
14.2.9 DoStatement
A looping statement for which the continuation condition is first tested after the first iteration.
Generalizations
• Statement
Synthesized Properties
• body : Block
The sequence of statements to be iteratively executed.
• condition : Expression
The expression to be evaluated to determine whether to continue looping.
Derived Properties
None
Constraints
[1] doStatementAssignmentsAfter
If the assigned source for a name after the condition expression is different than before the do statement,
then the assigned source of the name after the do statement is the do statement. Otherwise it is the same
as before the do statement.
[2] doStatementAssignmentsBefore
The assignments before the block of a do statement are the same as the assignments before the do
statement. The assignments before the condition expression of a do statement are the same assignments
after the block.
[3] doStatementCondition
The condition expression of a do statement must have type Boolean and a multiplicity upper bound of 1.
Helper Operations
None
14.2.10 EmptyStatement
Generalizations
• Statement
Synthesized Properties
None
Derived Properties
None
Constraints
[1] emptyStatementAssignmentsAfter
The assignments after and empty statement are the same as the assignments before the statement.
Helper Operations
[1] annotationAllowed ( in annotation : Annotation ) : Boolean
An empty statement may not have any annotations.
14.2.11 ExpressionStatement
Generalizations
• Statement
Synthesized Properties
• expression : Expression
The expression to be evaluated.
Derived Properties
None
Constraints
[1] expressionStatementAssignmentsAfter
The assignments after an expression statement are the same as the assignments after its expression.
Helper Operations
None
14.2.12 ForStatement
A looping statement that gives successive values to one or more loop variables on each iteration.
Generalizations
• Statement
Synthesized Properties
• body : Block
The sequence of statements to be iteratively executed.
Derived Properties
• isParallel : Boolean
Whether the for statement is parallel.
Constraints
[1] forStatementAssignmentsAfter
The loop variables are unassigned after a for statement. Other than the loop variables, if the assigned
source for a name after the body of a for statement is the same as after the for variable definitions, then
the assigned source for the name after the for statement is the same as after the for variable definitions.
If a name is unassigned after the for variable definitions, then it is unassigned after the for statement
(even if it is assigned in the body of the for statement). If, after the loop variable definitions, a name has
an assigned source, and it has a different assigned source after the body of the for statement, then the
assigned source after the for statement is the for statement itself.
[2] forStatementAssignmentsBefore
The assignments before a loop variable definition in a for statement are the same as before the for
statement. The assignments before the body of the statement include all the assignments before the
statement plus any new assignments from the loop variable definitions, except that, if the statement is
parallel, the assigned sources of any names given in @parallel annotations are changed to be the for
statement itself.
[3] forStatementEnclosedStatements
The enclosing statement for all statements in the body of a for statement are the for statement.
[5] forStatementLoopVariables
The assigned sources for loop variables after the body of a for statement must be the for statement (the
same as before the body).
[6] forStatementParallelAnnotationNames
A @parallel annotation of a for statement may include a list of names. Each such name must be already
assigned after the loop variable definitions of the for statement, with a multiplicity of [0..*]. These
names may only be used within the body of the for statement as the first argument to for the
CollectionFunctions::add behavior.
[7] forStatementParallelAssignmentsAfter
If, after the loop variable definitions of a parallel for statement, a name has an assigned source, then it
must have the same assigned source after the block of the for statement. Other than for names defined in
the @parallel annotation of the for statement, the assigned source for such names is the same after the
for statement as before it. Any names defined in the @parallel annotation have the for statement itself as
their assigned source after the for statement. Other than names given in the @parallel annotation, if a
name is unassigned after the loop variable definitions, then it is considered unassigned after the for
statement, even if it is assigned in the block of the for statement.
[8] forStatementVariableDefinitions
The isFirst attribute of the first loop variable definition for a for statement is true while the isFirst
attribute if false for any other definitions.
Helper Operations
[1] annotationAllowed ( in annotation : Annotation ) : Boolean
In addition to an @isolated annotation, a for statement may have a @parallel annotation.
14.2.13 IfStatement
A conditional statement that executes (at most) one of a set of clauses based on boolean conditions.
Generalizations
• Statement
Synthesized Properties
• finalClause : Block [0..1]
A sequence of statements to be executed if no other clause has a successful condition.
Derived Properties
• isAssured : Boolean
Whether at least one condition in the if statement is assured to evaluate to true.
• isDetermined : Boolean
Whether at most one condition in the if statement will ever to evaluate to true.
Constraints
[1] ifStatementAssignmentsAfter
If an if statement does not have a final else clause, then any name that is unassigned before the if
statement is unassigned after the if statement. If an if statement does have a final else clause, then any
name that is unassigned before the if statement and is assigned after any one clause of the if statement
must also be assigned after every other clause. The type of such names after the if statement is the
effective common ancestor of the types of the name in each clause with a multiplicity lower bound that
is the minimum of the lower bound for the name in each clause and a multiplicity upper bound that is the
maximum for the name in each clause. For a name that has an assigned source after any clause of an if
statement that is different than before that clause, then the assigned source after the if statement is the if
statement. Otherwise, the assigned source of a name after the if statement is the same as before the if
statement.
[2] ifStatementAssignmentsBefore
The assignments before all the non-final clauses of an if statement are the same as the assignments
before the if statement. If the statement has a final clause, then the assignments before that clause are
also the same as the assignments before the if statement.
[3] ifStatementEnclosedStatements
The enclosing statement of all the statements in the bodies of all non-final clauses and in the final clause
(if any) of an if statement is the if statement.
[4] ifStatementIsAssuredDerivation
An if statement is assured if it has an @assured annotation.
[5] ifStatementIsDeterminedDerivation
An if statement is determined if it has an @determined annotation.
Helper Operations
[1] annotationAllowed ( in annotation : Annotation ) : Boolean
In addition to an @isolated annotation, an if statement may have @assured and @determined
annotations. They may not have arguments.
Generalizations
• Statement
Synthesized Properties
• code : String
The in-line code to be executed.
• language : String
The name of the language in which the code is written.
Derived Properties
None
Constraints
[1] inLineStatementAssignmentsAfter
The assignments after an in-line statement are the same as the assignments before the statement.
Helper Operations
None
14.2.15 LocalNameDeclarationStatement
A statement that declares the type of a local name and assigns it an initial value.
Generalizations
• Statement
Synthesized Properties
• expression : Expression
The expression to be evaluated to provide the initial value to be assigned to the local name.
• name : String
The local name being declared.
Derived Properties
• type : ElementReference [0..1]
Constraints
[1] localNameDeclarationStatementAssignmentsAfter
The assignments after a local name declaration statement are the assignments before the statement plus a
new assignment for the local name defined by the statement. The assigned source for the local name is
the local name declaration statement. The local name has the type denoted by the type name if this is not
empty and is untyped otherwise. If the statement has multiplicity, then the multiplicity of the local name
is [0..*], otherwise it is [0..1].
[2] localNameDeclarationStatementAssignmentsBefore
The assignments before the expression of a local name declaration statement are the same as the
assignments before the statement.
[3] localNameDeclarationStatementExpressionMultiplicity
If a local name declaration statement does not have multiplicity, then the multiplicity of upper bound of
the assigned expression must not be greater than 1.
[4] localNameDeclarationStatementLocalName
The local name in a local name declaration statement must be unassigned before the statement and
before the expression in the statement. It must remain unassigned after the expression.
[5] localNameDeclarationStatementType
If the type name in a local name declaration statement is not empty, then it must resolve to a non-
template classifier and the expression must be assignable to that classifier.
[6] localNameDeclarationStatementTypeDerivation
The type of a local name declaration statement with a type name is the single classifier referent of the
type name. Otherwise it is the type of the expression of the statement.
Helper Operations
None
14.2.16 LoopVariableDefinition
Generalizations
• SyntaxElement
Synthesized Properties
• expression1 : Expression
If there is only one expression, then this expression is evaluated to produce a sequence of values to
be assigned to the loop variable on successive iterations. Otherwise it is evaluated to provide the first
value of a range of values to be assigned to the loop variable.
NOTE: This flag is necessary to because a variable that is explicitly declared to have type "any" will
have an empty typeName, just like a variable whose type is to be inferred, but, in the former case,
the type is actually intended to be empty, not inferred.
• variable : String
The name of the loop variable.
Derived Properties
• assignmentAfter : AssignedSource [*]
The assigned sources for local names available lexically after this loop variable definition. This
includes not only any assignments made within the statement, but also any assignments that are
unchanged from before the statement.
• isCollectionConversion : Boolean
Whether collection conversion is required.
• isFirst : Boolean
Whether this definition is the first in the list of definitions in the enclosing for statement.
Constraints
[1] loopVariableDefinitionAssignmentAfterDerivation
The assignments after a loop variable definition include the assignments after the expression (or
expressions) of the definition plus a new assigned source for the loop variable itself. The assigned
source for the loop variable is the loop variable definition. The multiplicity upper bound for the variable
is 1. The multiplicity lower bound is 1 if the loop variable definition is the first in a for statement and 0
otherwise. If collection conversion is not required, then the variable has the inferred or declared type
from the definition. If collection conversion is required, then the variable has the argument type of the
[2] loopVariableDefinitionAssignmentsBefore
The assignments before the expressions of a loop variable definition are the assignments before the loop
variable definition.
[3] loopVariableDefinitionDeclaredType
If the type of a loop variable definition is not inferred, then the first expression of the definition must
have a type that conforms to the declared type.
[4] loopVariableDefinitionRangeExpressions
If a loop variable definition has two expressions, then both expressions must have type Integer and a
multiplicity upper bound of 1, and no name may be newly assigned or reassigned in more than one of
the expressions.
[5] loopVariableDefinitionTypeDerivation
If the type of a loop variable is not inferred, then the variable has the type denoted by the type name, if it
is not empty, and is untyped otherwise. If the type is inferred, them the variable has the same as the type
of the expression in its definition.
[6] loopVariableDefinitionTypeName
If a loop variable definition has a type name, then this name must resolve to a non-template classifier.
[7] loopVariableDefinitionVariable
The variable name given in a loop variable definition must be unassigned after the expression or
expressions in the definition.
[8] loopVariableIsCollectionConversionDerivation
Collection conversion is required for a loop variable definition if the type for the definition is the
instantiation of a collection class and the multiplicity upper bound of the first expression is no greater
than 1.
Helper Operations
None
14.2.17 NonFinalClause
A clause of an if statement with a conditional expression and a sequence of statements that may be
executed if the condition is true.
Generalizations
• SyntaxElement
Synthesized Properties
• body : Block
• condition : Expression
The expression that is evaluated to determine whether the clause body may be executed.
Derived Properties
None
Constraints
[1] nonFinalClauseAssignmentsBeforeBody
The assignments before the body of a non-final clause are the assignments after the condition.
[2] nonFinalClauseConditionLocalNames
If a name is unassigned before the condition expression of a non-final clause, then it must be unassigned
after that expression (i.e., new local names may not be defined in the condition).
[3] nonFinalClauseConditionType
The condition of a non-final clause must have type Boolean and a multiplicity upper bound no greater
than 1.
Helper Operations
[1] assignmentsAfter ( ) : AssignedSource [*]
The assignments after a non-final clause are the assignments after the block of the clause.
14.2.18 QualifiedNameList
Generalizations
• SyntaxElement
Synthesized Properties
• name : QualifiedName [1..*]
The names in the group.
Derived Properties
None
Constraints
None
14.2.19 ReturnStatement
Generalizations
• Statement
Synthesized Properties
• expression : Expression
The expression to be evaluated to provide the returned value.
Derived Properties
• behavior : ElementReference
A reference to the enclosing behavior for this return statement.
Constraints
[1] returnStatementAssignmentsAfter
The assignments after a return statement are the same as the assignments after the expression of the
return statement.
[2] returnStatementAssignmentsBefore
The assignments before the expression of a return statement are the same as the assignments before the
statement.
[3] returnStatementContext
The behavior containing the return statement must have a return parameter. The expression of the return
statement must be assignable to that return parameter.
Helper Operations
None
14.2.20 Statement
Generalizations
• DocumentedElement
Synthesized Properties
• annotation : Annotation [*]
The annotations applied to this statement.
• isIsolated : Boolean
Whether this statement should be executed in isolation.
Constraints
[1] statementAnnotationsAllowed
All the annotations of a statement must be allowed, as given by the annotationAllowed operation for the
statement.
[2] statementIsIsolatedDerivation
A statement is isolated if it has an @isolated annotation.
[3] statementUniqueAssignments
No name may be assigned more than once before or after a statement.
Helper Operations
[1] annotationAllowed ( in annotation : Annotation ) : Boolean
Returns true if the given annotation is allowed for this kind of statement. By default, only an @isolated
annotation is allowed, with no arguments. This operation is redefined only in subclasses of Statement for
kinds of statements that allow different annotations than this default.
14.2.21 SwitchClause
A clause in a switch statement with a set of cases and a sequence of statements that may be executed if
one of the cases matches the switch value.
Generalizations
• SyntaxElement
Synthesized Properties
• block : Block
The sequence of statements that may be executed if one of the cases matches the switch value.
Derived Properties
None
Constraints
[1] switchClauseAssignmentsBefore
The assignments before any case expression of a switch clause are the same as the assignments before
the clause. The assignments before the block of a switch clause are the assignments after all case
expressions.
[2] switchClauseCaseLocalNames
If a name is unassigned before a switch clause, then it must be unassigned after all case expressions of
the clause (i.e., new local names may not be defined in case expressions).
Helper Operations
[1] assignmentsAfter ( ) : AssignedSource [*]
The assignments after a switch clause are the assignments after the block of the switch clause.
14.2.22 SwitchStatement
A statement that executes (at most) one of a set of statement sequences based on matching a switch
value to a set of test cases.
Generalizations
• Statement
Synthesized Properties
• defaultClause : Block [0..1]
A sequence of statements to be executed if no switch clause case matches the switch value.
• expression : Expression
The expression to be evaluated to provide the switch value.
Derived Properties
• isAssured : Boolean
• isDetermined : Boolean
Whether at most one case in the if statement will ever to match.
Constraints
[1] switchStatementAssignments
If a switch statement does not have a final default clause, then any name that is unassigned before the
switch statement is unassigned after the switch statement. If a switch statement does have a final default
clause, then any name that is unassigned before the switch statement and is assigned after any one clause
of the switch statement must also be assigned after every other clause. The type of such names after the
switch statement is the effective common ancestor of the types of the name in each clause with a
multiplicity lower bound that is the minimum of the lower bound for the name in each clause and a
multiplicity upper bound that is the maximum for the name in each clause.
[2] switchStatementAssignmentsAfter
If a name has an assigned source after any clause of a switch statement that is different than before that
clause (including newly defined names), the assigned source after the switch statement is the switch
statement. Otherwise, the assigned source of a name after the switch statement is the same as before the
switch statement.
[3] switchStatementAssignmentsBefore
The assignments before all clauses of a switch statement are the same as the assignments before the
switch statement.
[4] switchStatementCaseAssignments
The same local name may not be assigned in more than one case expression in a switch statement.
[5] switchStatementEnclosedStatements
[6] switchStatementExpression
[7] switchStatementIsAssuredDerivation
An switch statement is assured if it has an @assured annotation.
[8] switchStatementIsDeterminedDerivation
An switch statement is determined if it has an @determined annotation.
Helper Operations
[1] annotationAllowed ( in annotation : Annotation ) : Boolean
In addition to an @isolated annotation, a switch statement may have @assured and @determined
annotations. They may not have arguments.
A looping statement for which the continuation condition is first tested before the first iteration.
Generalizations
• Statement
Synthesized Properties
• body : Block
The sequence of statements to be iteratively executed.
• condition : Expression
The expression to be evaluated to determine whether to continue looping.
Derived Properties
None
Constraints
[1] whileStatementAssignmentsAfter
If a name is assigned before the block, but the assigned source for the name after the block is different
than before the block, then the assigned source of the name after the while statement is the while
statement. Otherwise it is the same as before the block. If a name is unassigned before the block of a
while statement, then it is unassigned after the while statement, even if it is assigned after the block.
[2] whileStatementAssignmentsBefore
The assignments before the condition expression of a while statement are the same as the assignments
before the while statement. The assignments before the block of the while statement are the same as the
assignments after the condition expression.
[3] whileStatementCondition
The condition expression of a while statement must have type Boolean and a multiplicity upper bound of
1.
[4] whileStatementEnclosedStatements
The enclosing statement for all statements in the body of a while statement are the while statement.
Helper Operations
None
.
Figure 15-99 Unit and Namespace Definitions
Generalizations
• ClassDefinition
Synthesized Properties
• classifierBehavior : ActivityDefinition [0..1]
The definition of an activity (which may be a stub) to act as the classifier behavior of the active
class.
Derived Properties
None
Helper Operations
[1] matchForStub ( in unit : UnitDefinition ) : Boolean
Returns true if the given unit definition matches this active class definition considered as a class
definition and the subunit is for an active class definition.
15.2.2 ActivityDefinition
The definition of an activity, with any formal parameters defined as owned members.
Generalizations
• ClassifierDefinition
Synthesized Properties
• body : Block [0..1]
The sequence of statements that defines the behavior of the activity (empty for a stub).
Derived Properties
None
Constraints
[1] activityDefinitionPrimitive
If an activity definition is primitive, then it must have a body that is empty.
[2] activityDefinitionSpecialization
An activity definition may not have a specialization list.
Helper Operations
[1] annotationAllowed ( in annotation : StereotypeAnnotation ) : Boolean
In addition to the annotations allowed for classifiers in general, an activity definition allows @primitive
annotations and any stereotype whose metaclass is consistent with Activity.
Generalizations
• ClassifierDefinition
Synthesized Properties
None
Derived Properties
None
Constraints
[1] associationDefinitionSpecializationReferent
The specialization referents of an association definition must all be associations.
Helper Operations
[1] annotationAllowed ( in annotation : StereotypeAnnotation ) : Boolean
In addition to the annotations allowed for classifiers in general, an association definition allows an
annotation for any stereotype whose metaclass is consistent with Association.
15.2.4 ClassDefinition
The definition of a class, whose members may be properties, operations, signals or signal receptions.
Generalizations
• ClassifierDefinition
Synthesized Properties
None
Derived Properties
None
Helper Operations
[1] annotationAllowed ( in annotation : StereotypeAnnotation ) : Boolean
In addition to the annotations allowed for classifiers in general, a class definition allows an annotation
for any stereotype whose metaclass is consistent with Class.
15.2.5 ClassifierDefinition
Generalizations
• NamespaceDefinition
Synthesized Properties
• isAbstract : Boolean = false
Whether the classifier is abstract or not.
Derived Properties
• specializationReferent : ElementReference [*]
References to the classifiers to which the names in the specialization list resolve.
Constraints
[1] classifierDefinitionInheritedMembers
The members of a classifier definition include non-private members inherited from the classifiers it
specializes. The visibility of inherited members is as specified in the UML Superstructure, Subclause
7.3.8.
[3] classifierDefinitionSpecializationReferentDerivation
The specialization referents of a classifier definition are the classifiers denoted by the names in the
specialization list for the classifier definition.
Helper Operations
[1] matchForStub ( in unit : UnitDefinition ) : Boolean
The namespace definition associated with the given unit definition must be a classifier definition. The
subunit classifier definition may be abstract if and only if the subunit classifier definition is abstract. The
subunit classifier definition must have the same specialization referents as the stub classifier definition.
(Note that it is the referents that must match, not the exact names or the ordering of those names in the
specialization list.) The subunit classifier definition must also have a matching classifier template
parameter for each classifier template parameter of the stub classifier definition. Two template
parameters match if they have same names and the same specialization referents.
15.2.6 ClassifierTemplateParameter
The definition of a classifier template parameter, which acts as a classifier within the definition of the
template.
Generalizations
• ClassifierDefinition
Synthesized Properties
None
Derived Properties
None
Constraints
None
Helper Operations
[1] annotationAllowed ( in annotation : StereotypeAnnotation ) : Boolean
Annotations are not allowed on classifier template parameters.
Generalizations
• ClassifierDefinition
Synthesized Properties
None
Derived Properties
None
Constraints
[1] dataTypeDefinitionPrimitive
If a data type is primitive, then it may not have any owned members.
[2] dataTypeDefinitionSpecializationReferent
The specialization referents of a data type definition must all be data types.
Helper Operations
[1] annotationAllowed ( in annotation : StereotypeAnnotation ) : Boolean
In addition to the annotations allowed for classifiers in general, a data type definition allows @primitive
annotations plus any stereotype whose metaclass is consistent with DataType.
15.2.8 ElementImportReference
Generalizations
• ImportReference
Synthesized Properties
• alias : String [0..1]
The alias to be used as the name for the imported element in the importing unit’s namespace.
Constraints
None
Helper Operations
None
15.2.9 EnumerationDefinition
The definition of an enumeration, whose members must all be enumeration literal names.
Generalizations
• ClassifierDefinition
Synthesized Properties
None
Derived Properties
None
Constraints
[1] classDefinitionSpecializationReferent
The specialization referents of a class definition must all be classes. A class definition may not have any
referents that are active classes unless this is an active class definition.
Helper Operations
[1] annotationAllowed ( in annotation : StereotypeAnnotation ) : Boolean
In addition to the annotations allowed for classifiers in general, an enumeration definition allows an
annotation for any stereotype whose metaclass is consistent with Enumeration.
15.2.10 EnumerationLiteralName
Generalizations
• Member
Derived Properties
None
Constraints
None
Helper Operations
[1] annotationAllowed ( in annotation : StereotypeAnnotation ) : Boolean
Returns false. (Enumeration literal name cannot have annotations.)
15.2.11 FormalParameter
Generalizations
• TypedElementDefinition
Synthesized Properties
• direction : String
An indication of the direction of the parameter being defined.
Derived Properties
None
Constraints
None
Helper Operations
[1] annotationAllowed ( in annotation : StereotypeAnnotation ) : Boolean
Returns true if the annotation is for a stereotype that has a metaclass consistent with Parameter.
15.2.12 ImportedMember
Generalizations
• Member
Derived Properties
None
Constraints
[1] importedElementFeatureDerivation
An imported element is a feature if its referent is a feature.
[2] importedElementNotStub
An imported element is not a stub.
Helper Operations
[1] annotationAllowed ( in annotation : StereotypeAnnotation ) : Boolean
Returns false. (Imported members do not have annotations.)
15.2.13 ImportReference
Generalizations
• SyntaxElement
Synthesized Properties
• referentName : QualifiedName
The name of the element or package to be imported.
• unit : UnitDefinition
The unit that is making this import reference.
• visibility : String
An indication of the visibility of the import.
Constraints
[1] importReferenceReferent
The referent name of an import reference must resolve to a single element with public or empty
visibility.
[2] importReferenceReferentDerivation
The referent of an import reference is the element denoted by the referent name.
Helper Operations
None
15.2.14 Member
Generalizations
• DocumentedElement
Synthesized Properties
• annotation : StereotypeAnnotation [*]
The stereotype annotations on this member definition.
• name : String
The name of the member.
Derived Properties
• isExternal : Boolean
Whether this member is external or not.
• isPrimitive : Boolean
Whether this member is a primitive or not.
Constraints
[1] memberAnnotations
All stereotype annotations for a member must be allowed, as determined using the stereotypeAllowed
operation.
[2] memberExternal
If a member is external then it must be a stub.
[3] memberIsExternalDerivation
A member is external if it has an @external derivation.
[4] memberIsPrimitiveDerivation
A member is primitive if it has a @primitive annotation.
[5] memberPrimitive
If a member is primitive, then it may not be a stub and it may not have any owned members that are
template parameters.
[6] memberStub
If a member is a stub and is not external, then there must be a single subunit with the same qualified
name as the stub that matches the stub, as determined by the matchForStub operation.
[7] memberStubStereotypes
If a member is a stub, then the it must not have any stereotype annotations that are the same as its
subunit. Two stereotype annotations are the same if they are for the same stereotype.
[8] memberSubunitDerivation
If the member is a stub and is not external, then its corresponding subunit is a unit definition with the
same fully qualified name as the stub.
Helper Operations
[1] annotationAllowed ( in annotation : StereotypeAnnotation ) : Boolean
Returns true of the given stereotype annotation is allowed for this kind of element.
15.2.15 NamespaceDefinition
Generalizations
• Member
Synthesized Properties
• ownedMember : Member [*]
The definitions of owned members of the namespace.
Derived Properties
• member : Member [*]
The owned and imported members of a namespace definition.
Constraints
[1] namespaceDefinitionMemberDerivation
The members of a namespace definition include references to all owned members. Also, if the
namespace definition has a unit with imports, then the members include imported members with
referents to all imported elements. The imported elements and their visibility are determined as given in
the UML Superstructure. The name of an imported member is the name of the imported element or its
alias, if one has been given for it. Elements that would be indistinguishable from each other or from an
owned member (as determined by the Member::isDistinguishableFrom operation) are not imported.
Helper Operations
[1] annotationAllowed ( in annotation : StereotypeAnnotation ) : Boolean
Returns true if the annotation is @external.
15.2.16 OperationDefinition
The definition of an operation, with any formal parameters defined as owned members.
Generalizations
• NamespaceDefinition
Synthesized Properties
• body : Block [0..1]
The sequence of statements that defines the behavior of the operation (empty for a stub).
Derived Properties
• isConstructor : Boolean
Whether this operation definition is for a constructor.
• isDestructor : Boolean
Whether this operation definition is for a destructor.
Constraints
[1] operationDefinitionConstructor
If an operation definition is a constructor, any redefined operation for it must also be a constructor. The
body of a constructor may contain an alternative constructor invocation for another constructor in the
same class or super constructor invocations for constructors in immediate superclasses.
[2] operationDefinitionConstructorDestructor
An operation definition cannot be both a constructor and a destructor.
[4] operationDefinitionIsConstructorDefinition
An operation definition is a constructor if it has a @Create annotation.
[5] operationDefinitionIsDestructorDefinition
An operation definition is a destructor if it has a @Destroy annotation.
[6] operationDefinitionIsFeatureDerivation
An operation definition is a feature.
[7] operationDefinitionNamespace
The namespace for an operation definition must be a class definition. If the operation definition is
abstract, then the class definition must be abstract.
[8] operationDefinitionRedefinedOperations
The redefined operations of an operation definition must have formal parameters that match each of the
formal parameters of this operation definition, in order. Two formal parameters match if they have the
same direction, name, multiplicity bounds, ordering, uniqueness and type reference.
[9] operationDefinitionRedefinedOperationsDerivation
If an operation definition has a redefinition list, its redefined operations are the referent operations of the
names in the redefinition list for the operation definition. Otherwise, the redefined operations are any
operations that would otherwise be indistinguishable from the operation being defined in this operation
definition.
[10] operationDefinitionRedefinition
Each name in the redefinition list of an operation definition must have a signal referent that is an
operation. This operation must be a non-private operation that is a member of a specialization referent of
the class definition of the operation definition.
Helper Operations
[1] annotationAllowed ( in annotation : StereotypeAnnotation ) : Boolean
Returns true if the annotation is for a stereotype that has a metaclass consistent with Operation.
15.2.17 PackageDefinition
Generalizations
• NamespaceDefinition
Synthesized Properties
None
Derived Properties
• appliedProfile : Profile [*]
The profiles applied (directly) to this package.
Constraints
[1] packageDefinitionAppliedProfileDerivation
The applied profiles of a package definition are the profiles listed in any @apply annotations on the
package.
Helper Operations
[1] annotationAllowed ( in annotation : StereotypeAnnotation ) : Boolean
In addition to the annotations allowed on any namespace definition, a package definition allows @apply
annotations plus any stereotype whose metaclass is consistent with Package.
15.2.18 PackageImportReference
Generalizations
• ImportReference
Synthesized Properties
None
Constraints
[1] packageImportReferenceReferent
The referent of a package import must be a package.
Helper Operations
None
15.2.19 PropertyDefinition
Generalizations
• TypedElementDefinition
Synthesized Properties
• initializer : Expression [0..1]
The expression to be evaluated to initialize the property.
Derived Properties
• isBitStringConversion : Boolean
Whether BitString conversion is required for the initialization of this property.
• isCollectionConversion : Boolean
Whether collection conversion is required for the initialization of this property.
Constraints
[1] propertyDefinitionInitializer
If a property definition has an initializer, then the initializer expression must be assignable to the
property definition.
[2] propertyDefinitionIsBitStringConversion
A property definition requires BitString conversion if its type is BitString and the type of its initializer is
Integer or a collection class whose argument type is Integer.
[3] propertyDefinitionIsCollectionConversionDerivation
A property definition requires collection conversion if its initializer has a collection class as its type and
the property definition does not.
Helper Operations
[1] annotationAllowed ( in annotation : StereotypeAnnotation ) : Boolean
Returns true if the annotation is for a stereotype that has a metaclass consistent with Property.
15.2.20 ReceptionDefinition
Generalizations
• Member
Synthesized Properties
• signalName : QualifiedName
The name of the signal to be received.
Derived Properties
• signal : ElementReference
Constraints
[1] receptionDefinitionIsFeatureDerivation
A reception definition is a feature.
[2] receptionDefinitionSignalDerivation
The signal for a reception definition is the signal referent of the signal name for the reception definition.
[3] receptionDefinitionSignalName
The signal name for a reception definition must have a single referent that is a signal. This referent must
not e a template.
Helper Operations
[1] annotationAllowed ( in annotation : StereotypeAnnotation ) : Boolean
Returns true if the annotation is for a stereotype that has a metaclass consistent with Reception.
Generalizations
• ClassifierDefinition
Synthesized Properties
None
Derived Properties
None
Constraints
[1] signalDefinitionSpecializationReferent
The specialization referents of a signal definition must all be signals.
Helper Operations
[1] annotationAllowed ( in annotation : StereotypeAnnotation ) : Boolean
In addition to the annotations allowed for classifiers in general, a signal definition allows an annotation
for any stereotype whose metaclass is consistent with Signal.
15.2.22 SignalReceptionDefinition
The definition of both a signal and a reception of that signal as a feature of the containing active class.
Generalizations
• SignalDefinition
Synthesized Properties
None
Derived Properties
None
Helper Operations
None
15.2.23 StereotypeAnnotation
An annotation of a member definition indicating the application of a stereotype (or one of a small
number of special-case annotations).
Generalizations
• SyntaxElement
Synthesized Properties
• names : QualifiedNameList [0..1]
A set of references to model elements required for the stereotype being applied.
• stereotypeName : QualifiedName
The name of the stereotype being applied.
Derived Properties
• stereotype : Stereotype [0..1]
The stereotype denoted by the stereotype name.
Constraints
[1] stereotypeAnnotationApply
If the stereotype name of a stereotype annotation is "apply", then it must have a name list and all of the
names in the list must resolve to profiles.
[2] stereotypeAnnotationExternal
If the stereotype name of a stereotype annotation is "external", then it may optionally have a single
tagged value with the name "file" and no operator.
[3] stereotypeAnnotationNames
If a stereotype annotation has a stereotype and a list of names, then all the names in the list must resolve
to visible model elements and the stereotype must have a single attribute with a (metaclass) type and
multiplicity that are consistent with the types and number of the elements denoted by the given names.
[5] stereotypeAnnotationStereotypeDerivation
Unless the stereotype name is "apply", "primitive" or "external" then the stereotype for a stereotype
annotation is the stereotype denoted by the stereotype name.
[6] stereotypeAnnotationStereotypeName
The stereotype name of a stereotype annotation must either be one of "apply", "primitive" or "external",
or it must denote a single stereotype from a profile applied to an enclosing package. The stereotype
name does not need to be qualified if there is only one applied profile with a stereotype of that name or
if the there is a standard UML profile with the name.
[7] stereotypeAnnotationTaggedValues
If a stereotype annotation has a stereotype and tagged values, then the each tagged value must have the
name of an attribute of the stereotype and a value that is legally interpretable for the type of that
attribute.
Helper Operations
None
15.2.24 TaggedValue
Generalizations
• SyntaxElement
Synthesized Properties
• name : String
The name of the stereotype attribute to be assigned a value.
• value : String
The string image of a literal value to be assigned to the stereotype attribute.
Derived Properties
None
Constraints
None
15.2.25 TaggedValueList
Generalizations
• SyntaxElement
Synthesized Properties
• taggedValue : TaggedValue [*]
The tagged values in the set.
Derived Properties
None
Constraints
None
Helper Operations
None
15.2.26 TypedElementDefinition
Generalizations
• Member
Synthesized Properties
• isNonunique : Boolean = false
Whether the element being defined is non-unique.
Derived Properties
• lower : Integer
The multiplicity lower bound of the element being defined.
• upper : UnlimitedNatural
The multiplicity upper bound of the element being defined.
Constraints
[1] typedElementDefinitionLowerDerivation
If the lower bound string image of a typed element definition is not empty, then the integer lower bound
is the integer value of the lower bound string. Otherwise the lower bound is equal to the upper bound,
unless the upper bound is unbounded, in which case the lower bound is 0.
[2] typedElementDefinitionTypeDerivation
The type of a typed element definition is the single classifier referent of the type name.
[3] typedElementDefinitionTypeName
The type name of a typed element definition must have a single classifier referent. This referent may not
be a template.
[4] typedElementDefinitionUpperDerivation
The unlimited natural upper bound value is the unlimited natural value of the uper bound string (with
"*" representing the unbounded value).
Helper Operations
None
15.2.27 UnitDefinition
Generalizations
• DocumentedElement
Synthesized Properties
• import : ImportReference [*]
The set of references to imported elements or packages.
• definition : NamespaceDefinition
Derived Properties
• appliedProfile : Profile [*]
The profiles applied to this unit.
• isModelLibrary : Boolean
Whether this unit definition is for a model library or not.
Constraints
[1] unitDefinitionAppliedProfileDerivation
The profiles applied to a unit definition include any profiles applied to the containing namespace of the
unit definition. If the unit definition is for a package, then the applied profiles for the unit definition also
include the applied profiles for its associated package definition.
[2] unitDefinitionImplicitImports
Unless the unit definition is a model library, it has private package import references for all the sub-
packages of the Alf::Library package.
[3] unitDefinitionIsModelLibraryDerivation
A unit definition is for a model library if its associated namespace definition has a stereotype annotation
for the UML standard stereotype ModelLibrary.
[4] unitDefinitionNamespace
The declared namespace name for a unit definition, if any, must resolve to a UML namespace of an Alf
unit definition. If it is an Alf unit definition, then it must have a stub for this unit definition.
[5] unitDefinitionNamespaceDerivation
If a unit definition has a declared namespace name, then the containing namespace for the unit is the
referent for that name.
Helper Operations
None
17.1 General
1. An Alf expression that is not contained in any other Alf text is mapped to UML as an activity with
one parameter: a return parameter that gives the result of the expression.
2. Any Alf expression maps to some or all of the nodes and edges in an activity (sometimes called a
subgraph of the activity).
3. The mapping of each kind of expression identifies the result source element in the mapping. This is
the activity node to which an outgoing object flow may be attached in order to obtain the result of
the expression. The result values of the expression correspond to the values of the sequence of object
tokens produced on the flow. In some cases (such as when an expression is used in an expression
statement; see Subclause 9.6) the result source element may remain unconnected. In this case the
result values of the expression are lost.
17.8 Tuples
1. An empty tuple (i.e., a positional tuple with no argument expressions) is mapped to nothing. A non-
empty tuple is mapped to a structured activity node containing the mapping of each of its argument
expressions. There is a control flow from the structured activity node to the invocation action taking
input from the tuple mapping.
Shift Expressions
1. A shift expression is mapped as a behavior invocation (see Subclause 17.9) for the corresponding
primitive behavior from the Alf::Library::PrimitiveBehaviors package (see Subclause 11.3),
as given in Table 17-17. Note that this includes the possibility of performing bit string conversion on
the first operand.
Table 17-17 Primitive Behavior Equivalents for Arithmetic Operators
Operator Behavior
<< BitStringFunctions::'<<'
>> BitStringFunctions::'>>'
>>> BitStringFunctions::'>>>'
Relational Expressions
1. A relational expression is mapped as a behavior invocation (see Subclause 17.9) for the
corresponding primitive behavior from the Alf::Library::PrimitiveBehaviors package (see
Subclause 11.3), as given in Table 17-18.
Table 17-18 Primitive Behavior Equivalents for Relational Operators
Integer Behavior UnlimitedNatural Behavior
Operator
(isUnlimitedNatural=false) (isUnlimitedNatural=true)
< IntegerFunctions::'<' UnlimitedNaturalFunctions::'<'
> IntegerFunctions::'>' UnlimitedNaturalFunctions::'>'
<= IntegerFunctions::'<=' UnlimitedNaturalFunctions::'<='
>= IntegerFunctions::'>=' UnlimitedNaturalFunctions::'>='
Logical Expressions
1. A logical expression is mapped as a behavior invocation (see Subclause 17.9) for the corresponding
primitive behavior from the Alf::Library::PrimitiveBehaviors package (see Subclause 11.3),
as given in Table 17-19. Note that this includes the possibility of applying bit string conversion to
one or both operands, if the operator is bit-wise.
Classification Expressions
1. A classification expression maps to a read is classified object action for the named classifier with. If
the classification operator is instanceof, then isDirect=false. If the operator is hasType, then
isDirect=true. The object input pin of the action is the target of an object flow from the result source
element for the mapping of the operand expression. The result output pin of the action is the result
source element for the classification expression.
Equality Expressions
1. An equality expression is mapped to a test identity action. If the expression uses the operator ==, and
both operand expressions have a multiplicity lower bound of 1, then the input pins of the action are
the targets of object flows from the result source elements for the mappings of the argument
expressions. The output pin of the action is the result source pin for the equality expression.
2. If either operand expression has a multiplicity lower bound of 0, then the result of that expression is
first tested for being not empty using the library function Alf::Library::
PrimitiveBehaviors::SequenceFunctions::NotEmpty (see Subclause 11.3.6). The test identity
action is executed only if both argument expressions are non-empty. Otherwise, the equality
expression is true only if both argument expressions are empty.
NOTE. Despite the extra checks described above, the mapping for an equality expression still
always evaluates the operand expressions exactly once.
3. An equality expression that uses the operator != is mapped as above, but the result output pin of the
test identity action is connected by an object flow to the argument input pin of a call behavior action
for the library function Alf::Library::PrimitiveBehaviors:: BooleanFunctions::'!' (see
Subclause 11.3.1). The result source element is the result output pin of the call behavior action.
Conditional Logical Expressions
1. A conditional-and expression is mapped like a conditional-test expression (see Subclause 17.23)
whose first two operand expressions are the same as those of the conditional-and expression and
whose third operand expression is false.
2. A conditional-or operator expression is mapped like a conditional-test expression (see Subclause
17.23) whose first and third operand expressions are the same as the two operand expressions of the
conditional-or expression and whose second operand expression is true.
Compound Assignment
14. A compound assignment is mapped like a simple assignment expression for which the assigned
value is the result of a call behavior action for the primitive behavior corresponding to the compound
assignment operator. The arguments to the call behavior action come from the result source elements
of the mapping of the effective expression for the left-hand side and the right-hand side expression.
However, if the left-hand side is a property reference, then the primary expression for the reference
and any index expression are only mapped once with their values used both in the mapping of the
effective expression for the left-hand side and the updating of the left-hand side as a structural
feature.
18.1 General
1. Every statement is mapped to a single activity node (which may be a structured activity node with
nested structure). The specific mapping for each kind of statement is described in the following
subclauses.
2. If the static analysis of assignment indicates that a name with an assigned source has a different
assigned source after a statement than before the statement, and the statement maps to a structured
activity node (but not a conditional node or a loop node), then an input pin corresponding to that
name is added to the structured activity node. This input pin is the target of an incoming object flow
from the assigned source of the name before the statement. The input pin is also connected by an
outgoing object flow to a fork node contained in the structured activity node. This fork node acts as
the assigned source for the name within the mapping of the statement.
3. A block maps to the union of the nodes mapped from the statements in it. In addition, unless the
block is in a block statement annotated as being parallel (see Subclause 18.3), the node mapped from
each statement other than the last has a control flow targeted to the node mapped from the next
statement.
4. A statement for which @isolated is allowed is always mapped to structured activity node, and
annotating it @isolated results in the isIsolated property on this node being true. (Other
annotations are discussed with the description of the statements to which they apply.)
18.7 if Statements
Clauses
1. An if statement maps to a conditional node. Each if clause maps to a clause of the conditional
node. For a final if clause, the test part of the clause is a single value specification action for a
Boolean literal with value “true”.
2. Each clause specified in a concurrent clause set has as predecessors all clauses specified by the
immediately preceding concurrent clause set (if any) in the sequential clause set for the conditional
node. A final clause has as its predecessor all clauses specified by the immediately preceding
concurrent clause set.
3. The isAssured and/or isDetermined properties of the conditional node are set according to whether
the if statement is assured or determined.
Output Pins
4. The conditional node has a result output pin corresponding to each local name that is assigned in any
of the if clauses. Therefore, each clause of the conditional node also must have a body output pin
from within the clause identified for each result pin of the conditional node. If a name is assigned
within a clause and the assigned source for that name within the clause is a pin on an action within
the body of the clause, then that pin is used as the clause body output pin corresponding to that local
name. Otherwise, a structured activity node is added to the mapping of the clause as follows.
• The structured activity node has one input pin and one output pin, with an object flow
from the input pin to the output pin contained within the structured activity node.
• There is an object flow from the assigned source for the name after the clause (which
may be from inside or outside the clause) to the input pin of the structured activity node.
The output pin of the structured activity node is then used as the clause body output pin
corresponding to the name.
18.10 do Statements
Loop Node
1. A do statement maps to a loop node with isTestedFirst=false (see fUML Specification, Subclause
7.4.3). The loop node contains the activity nodes and edges mapped from both the block and the
condition expression (see Subclause 12.2) of the do statement. All the actions from the mapping of
the condition expression constitute the test part of the loop node. All the actions from the mapping of
the block form the body part.
2. If the result source element from the mapping of the condition expression is an output pin, then this
is the decider pin for the loop node. Otherwise, a structured activity node is added inside the loop
node as follows.
• The structured activity node has one input pin and one output pin, with an object flow
from the input pin to the output pin contained within the structured activity node.
• There is an object flow from the result source element from the mapping of the
expression to the input pin of the structured activity node.
The output pin of the structured activity node is then used as the decider pin.
Loop Variables
3. Any name that is assigned in the condition expression or block of the do statement is mapped to a
loop variable of the loop node. The loop variable corresponding to a name is used as the assigned
source before the block when mapping the do statement. If the name is assigned before the do
statement, then the corresponding loop variable input pin is the target of an incoming object flow
from the assigned source for the name before the do statement. Otherwise the loop variable input pin
is unconnected.
4. If the assigned source for the name after the condition expression of the do statement is an output
pin, then this output pin is identified as the body output pin corresponding to the loop variable for
the name. Otherwise, a structured activity node is added to the mapping of the body of the loop as
follows.
• The structured activity node has one input pin and one output pin, with an object flow
from the input pin to the output pin contained within the structured activity node.
• There is an object flow from the assigned source for the name after the block to the input
pin of the structured activity node.
is mapped equivalently to
{
list1 = (T[]) expr1;
list2 = (T[]) expr2;
…
size = list1->size();
i = 1;
while (i <= size) {
v1 = list1[i];
v2 = list2[i];
…
stmts
i++;
}
}
where list, size and i are arbitrary local names not otherwise used in the enclosing activity and T is
the type of expr1.
Parallel for Statements
4. A parallel for statement is always mapped to an expansion region, but with mode=parallel. Any
name listed in the @parallel annotation for the statement is mapped to an output expansion node
with that name and its assigned type. This expansion node provides the source element for the
assigned value for the name after the for statement.
19.1 General
Unit Definition
1. A unit definition maps to a specific kind of namespace according to the namespace definition for the
unit definition, as given in the appropriate subsequent subclause. If a namespace declaration is given,
the namespace mapped from the unit is an owned member of the declared namespace. If no
namespace declaration is given, then the unit must be a model unit and what namespace owns it, if
any, is not defined by the Alf specification.
2. If the unit is a model unit, then it has empty visibility. Otherwise, the unit visibility is given by the
stub declaration for it in the definition of its owning namespace.
Import Reference
3. An element import reference maps to an element import from the namespace to the named imported
element. The element import visibility is as given by the import visibility indicator. If there is an
alias part, then the given unqualified name becomes the element import alias.
4. A package import reference maps to a package import from the namespace to the named package.
The package import visibility is as given by the import visibility indicator.
Stereotype Annotation
5. A stereotype annotation, other than for the special cases given in Table 10-7, maps formally to the
application of the identified stereotype to the element mapped from the annotated member..
However, an implementation may also use such stereotypes to specify special implementation-
specific semantics for the annotated element, except for the standard stereotypes «Create» and
«Destroy», which are used in the standard Alf mapping for constructors and destructors and
«ModelLibrary», which is used to suppress the inclusion of implicit imports.
NOTE.
Even though activities are classes in UML, Alf does not provide any notation for defining attributes,
operations or receptions for activities. However, in order to allow for the use of Alf representation for
activities in larger enclosing models not represented in Alf, Alf allows activity model units to be active
and to have attributes, operations and receptions as features. But, since, these features cannot be
represented in Alf, it is tool specific how these features are attached to the activity.
Alf also does not provide any notation for specifying superclasses for an activity. However, Alf allows a
tool to provide means for specifying the superclasses for an activity (which may be regular classes or
activities) otherwise represented as an Alf model unit. Members are inherited from activity superclasses
in the same way as for regular classes (see Subclauses 10.4.2 and 10.4.3). But the semantics for
inheritance of behavior from activity superclasses is not specified.
with Expression as given in Subclause 8.1, Name as given in Subclause 7.5 and StatementSequence as
given in Subclause 9.1.
The guard constraint and behavior expression in a transition are semantically mapped to fUML as
follows, with the given constraints.
• A guard constraint expression must have type Boolean. The Alf expression for a guard constraint is
mapped to an activity with a return parameter of type Boolean and no other parameters (as discussed
in Subclause 8.1).
• If a behavior expression is given by a name, then this must be the name of the effect behavior owned
by the transition. The named behavior may be specified by any means supported by the execution
tool, in Alf or otherwise.
• If a behavior expression is given as an Alf statement sequence, then it maps to an activity (see
Subclause 9.1).
Consistent with UML Superstructure, Subclause 15.3.14, the execution of a transition proceeds as
follows:
1. If all the source states of the transition are in the active state configuration (or the source of the
transition is a choice point that has been reached), one of the triggers of the transition is satisfied by
the event occurrence being dispatched, and the transition has a guard constraint, then the guard
constraint behavior is invoked synchronously. The execution object for the call is destroyed once the
invocation is completed (see fUML Specification, Subclause 8.4.2.1, for an overview of execution
objects in fUML). If the transition has a guard constraint that returns false, then the execution of the
transition completes without further effect. Otherwise the transition is enabled to fire.
2. If the transition is enabled, then it may be selected to fire (per the rules of UML Superstructure,
Subclause 15.3.14). If it is not selected, then its execution completes without further effect.
Otherwise, execution proceeds as described below. (The description below only involves the
execution of the transition behavior itself. For the specification of the effect of the transition on the
state machine state configuration, see UML Superstructure, Subclause 15.3.14.)
3. If the transition has an effect behavior, then this behavior is invoked synchronously. The execution
object for the invocation is destroyed once the invocation is completed (see fUML Specification,
Subclause 8.4.2.1, for an overview of execution objects in fUML).
States
A state may optionally have an entry behavior, an exit behavior and/or a do-activity behavior. If a state
has one or more of these behaviors, then this is notated in the internal activities compartment of the
graphical symbol for the state as follows (see UML Superstructure, Subclause 15.3.11).
InternalActivity = ActivityLabel "/" BehaviorExpression
ActivityLabel = "entry" | "exit" | "do"
An assignment specification may be included (but is not required) for a call event for an operation with
parameters (other than a return parameter) or a signal event for a signal with attributes. The stated
semantics of an assignment specification require that the given names be names of attributes of the
context classifier for the state machine owning the transition and that the corresponding current event
data are assigned to attributes so named.
However, the abstract syntax for events does not provide any way to capture such assignment
specifications. Since UML semantics is formally defined on the abstract syntax, not any particular
concrete syntax, there is no clear way to formalize the semantics given for the assignment specification
notation.
One possible alternative is to use the assignment specification notation, but to treat the notation as
specifying parameters with the given names on the effect behavior for the transition. Then, when that
behavior is invoked, the current event data can be assigned to the behavior input parameters. For call
events, the behavior would have parameters corresponding to both the input and output parameters of
the called operation, with output parameters assigned after the behavior completes execution.
For this alternative, the effect behaviors on transitions would have to meet the following contraints.
• If a transition has more than one trigger or it has a single trigger that is not for a call event or a signal
event, then its effect behavior (if any) may not have any parameters. If a transition has a single
trigger for a call event or a signal event, then it may, but is not required, to have parameters, as given
below.
• The effect behavior for a transition with a single trigger for a call event may have parameters that
correspond, in order, to each of the parameters of the called operation. The direction, type and
multiplicity of the behavior parameters must be the same as those of the corresponding operation
parameters, but the names may be different.
• The effect behavior for a transition with a single trigger for a signal event may have in parameters
that correspond, in order, to each of the attributes of the received signal. The type and multiplicity of
the behavior parameters must be the same as those of the corresponding signal attributes, but the
names may be different.
The assignment specification notation could then be used to show the names (and optionally the types)
of the parameters of the effect behavior of a transition (other than the return parameter for a call event).
The advantage of this approach for Alf semantic integration is that, if an effect behavior with parameters
as given above is specified using Alf, then the named parameters can be accessed as usual as local
Notes
1. Alf allows the use of the usual UML multiplicity notation (see Subclause 10.5.2). The keyword
“sequence” indicates that the input list is an ordered sequence of integers that allows repetition of
values.
2. An Alf if statement has a C-like syntax and similar semantics (see Subclause 9.8).
3. An OCL-like notation can be used for sequence operations (see Subclause 8.3.17) such as isEmpty.
4. As would be expected, a return statement is used in Alf to provide the return value for an activity
(see Subclause 9.14).
5. In Alf, “null” denotes the empty set (see Subclause 8.3.15).
6. Alf uses the C-like notation of “=” for assignment (and “==” for equality). However, Alf does not
require that the types for local names be explicitly declared (see Subclause 9.6). The type for x is
7. Alf provides a familiar index notation for accessing the elements of a sequence (see Subclause
8.3.16). Note, however, that indexing is from 1, not 0.
8. Alf provides on OCL-like notation for flow expansion expressions (see Subclause 8.3.18). The
expression “list->select a (a < x)” is used to select all elements of list that are less than x.
Note that there is no required ordering of the tests on the elements of list, which may all be carried
out concurrently.
There are two major notational differences from OCL. First, the notation for an iterator variable is
different. Instead of the OCL form “select(a | …)”, Alf uses “select a (…)”. This avoids
ambiguity with the use of “|” for the Boolean “or” operator in Java/C syntax. Second, Alf requires
that an iterator variable always be given. Java-like expression syntax is not as rigorously object-
oriented as OCL syntax, and, therefore, not as amenable to an implicit form for the iterator context.
By requiring that the iterator variable be explicit, no special form is necessary for the expressions
used within the collection operation construct. For example, the OCL expression “devices->
select(oclIsKindOf(Sensor))” is written in the form “devices->select device (device
instanceof Sensor)” in Alf.
do { // See Note 3
while ((l < h) && (list[l] <= p)) { // See Note 4
l = l+1;
}
while ((h > l) && (list[h] >= p)) {
h = h-1;
}
if (l < h) {
t = list[l];
list[l] = list[h];
list[h] = t;
}
} while (l < h);
t = list[l];
list[l] = list[high];
list[high] = t;
Notes
1. Alf allows activity parameters with any of the UML directions, including out and inout (see
Subclause 10.4.8).
2. Statements within the statement sequence of a block delimited by “{…}” are executed sequentially
(see Subclause 9.1).
3. An Alf do…while statement has the familiar C-like syntax and semantics (see Subclause 9.11).
4. Alf uses the usual infix notation for arithmetic and relational operations (see Subclauses 8.6.1 and
8.6.4). The conditional and operator “&&” has the C-like semantics of only evaluating its second
argument if the first argument is true (see Subclause 8.6.8).
if (matchingCustomers->isEmpty()) {
customer = new Customer(); // See Note 4
customer.email = this.checkOutData.customerEmail;
} else {
customer = matchingCustomers[1]; // See Note 5
}
/**
Online Bookstore, Ordering Subsystem
*/
package Ordering
{
public active class ShoppingCart; // See Note 2
public active class Order;
public active class CreditCardCharge;
public active class Customer;
public active class ProductSelection;
public assoc R1
{
public 'selections are added to': ShoppingCart[0..*]; // See Note 3
public 'includes selections of': Product[1..*];
public 'product selection is': ProductSelection;
}
public assoc R2 {
public 'selections are purchased in': Order[0..1];
public 'is a purchase of selections in': ShoppingCart;
}
public assoc R3 {
public places: Order[1..*];
public 'is placed by': Customer[0..1];
}
public assoc R4 {
public 'is an attempt to pay for': Order;
public 'payment is attempted by': CreditCardCharge[0..*];
}
public assoc R5 {
public 'pays for': Order[0..1];
public 'is paid for by': CreditCardCharge[0..1];
}
}
Notes
1. The clause “private import ProductSpecification::Product;” denotes an element import of
the Product class in the ProductSpecification package. Use of “private” indicates a private
import—“public import ProduceSpecification::Product;” would indicate a public import.
Similarly. “private import DomainDataTypes::*;” denotes the (private) package import of the
package DomainDataTypes. That is, it is not just the package DomainDataTypes that is being
imported, but all the elements of that package.
2. All the classes in this package have classifier behaviors and are thus active. Only stubs are included
in this package specification, with the full definition of the class written separately. The use of stubs
/**
Active class for managing an order
*/
active class Order
{
public orderID: arbitrary_id;
public dateOrderPlaced: date;
public totalValue: Money;
public recipient: PersonalName;
public deliveryAddress: MailingAddress;
public contactPhone: TelephoneNumber;
}
do // See Note 3
{
accept (PaymentDeclined) {
/** 3. Payment Not Approved */
DeclineCharge();
Notes
1. The notation “receive signal Checkout” indicates the definition of both a signal called Checkout
within the Order namespace and the definition of a reception of that signal as a feature of the Order
class. A signal definition alone would be denoted “signal Checkout{…}”and a definition of a
reception for that signal would be “receive Checkout”. Note that, unlike the graphical UML
notation, in Alf the attributes (“parameters”) of the signal would not be repeated in the reception
definition.
6. Alf uses the usual object-oriented procedural notation for operation invocation.
7. The while statement provides structured iteration.
8. This is a compound accept statement. The additional “or accept” clause indicates waiting for
reception of either a PaymentDeclined or a PaymentApproved signal. If a PaymentDeclined signal
is received, then the statements associated with that accept clause (“this.DeclineCharge();”) are
executed. If a PaymentAccepted signal is received, then the statements associated with its accept
clause (“break;”) are executed.
9. The break statement terminates the enclosing while loop.
Figure B-107 gives a simplified data model for property management. Note in general the use of spaces
in names. This is allowed in a UML model and is not uncommon in business-oriented data models not
primarily driven by an information technology style.
(Note that underscores are used here to fill in the spaces in the names. The OCL Specification does
not seem to disallow spaces in names, but it is not clear how they would parse in the OCL syntax.)
5. The Property class is abstract with two concrete subclasses for Personal Property (property that
is movable, like vehicles and furniture) and Real Property (property that is immovable, like land
and buildings). The attributes of these subclasses are optional, because their value is not necessarily
known until the property is actually acquired (a property record can be established pending
acquisition, in order to generate a property identifier with which to track the acquisition).
In addition to the data structure shown in Figure B-107, the Property class has two operations. As
shown in Figure B-108, one operation is a constructor and the other handles the computation of the
derived value for the status attribute.
Figure B-111 shows the Property Management Service interface. For the purposes of this example,
each operation has a simple synchronous request/reply signature. Each operation takes a single in
parameter request of a specific request type and two out parameters. If the request is successful, a
success reply is returned in the reply parameter. Otherwise an error reply is returned in the error
parameter.
2. The Property Management Service Provider has an internal part that directly implements the
service. All requests through the port are delegated to this implementation.
3. The Property Management Service Provider has another part that is used by the Property
Management Service Implementation as a “factory” for creating unique identifiers to give to
property records when they are established.
Figure B-113 shows a model of the Property Management Service Implementation class.
C.3.4.1 Property
As discussed in Section C.3.1, the class Property has two operations, create property, which is a
constructor, and update status, which computes the derived value of the status attribute.
create property
namespace 'Property Management'::'Data Model'::Properties::Property;
// See Note 1
this.identifier = identifier;
this.name = name;
this.'update status'();
Notes
1. The namespace clause here includes the fully qualified name for the Property class, uniquely
identifying it within the model. Note also the use of single quotes to form names with spaces.
update status
namespace 'Property Management'::'Data Model'::Properties::Property;
/** Update the status of a property consistent with whether it has been
acquired or disposed.
*/
activity 'update status'() {
if (this.'acquisition data' -> isEmpty()) { // See Note 1
this.status = 'Property Status'::pending; // See Note 2
} else if (this.'disposition data' -> isEmpty()) {
this.status = 'Property Status'::acquired;
} else {
this.status = 'Property Status'::disposed;
}
}
Notes
1. The OCL-like notation “this.'acquisition data' -> isEmpty()” is used to test whether the
optional attribute acquisition data is empty.
2. The enumeration Property Status is visible in the scope of Property (it is in the same package),
so it can be used without import. However, the names of its enumeration literals still need to be
qualified.
Notes
1. Alf allows the use of the C-style “++” operator. In this case, the value of next identifier is
incremented, but the prior value is returned. That is, the return statement above is mapped as if it
were the following equivalent statement sequence:
Note in particular that fUML semantics requires that objects persist between activity invocations at a
specific execution locus, unless they are explicitly destroyed. The specification of the Property
Management Service takes advantage of this by effectively using the extent of the Property class as a
“database” of property records.
create reply
namespace 'Property Management'::'Service Model'::
'Property Management Service Implementation';
/** Create a reply message for a given message ID and property object */
activity 'create reply'(in requestId: String, in property: Property):
'Property Management Success Reply' {
Notes
2. Property Data is a data type, which may only be constructed using a default constructor. The
default constructor for a data type provides arguments for each of the attributes of the data type,
which are set here using a named-parameter notation.
establish
namespace 'Property Management'::'Service Model'::
'Property Management Service Implementation';
Notes
1. The notation “this.'property identifier factory'” maps to a read link action for the
association from the Property Management Service Implementation to the Identifier
Factory used to generate property identifiers.
NOTE. Components and parts are not in the fUML subset. However, by general UML semantics, it
is assumed that, when the Property Management Service Provider is instantiated, both its parts
are also instantiated. The connection between the parts then results in a link between the Property
Management Service Implementation instance and the Instance Factory instance. It is this link
that is read here. (See also the discussion in Annex A.2.)
2. The Property class has the named constructor create property, rather than a default constructor.
This is referenced in the constructor invocation by the qualified name “Property::'create
property'”. Note that if, instead, the constructor had had the same name as the class, then the
constructor could have been referenced simply using the class name, i.e., “new
Property(identifier, request.name)”.
property =
Property -> select p (p.identifier == request.'property identifier');
// See Note 1
} else {
property.'acquisition data' = request.'property acquisition data';
// See Note 2
property.'update status'();
Notes
1. The select expression is used to select the elements from a collection that meet the given condition.
The type name “Property” here is used as a shorthand for “Property.allInstances()”—that is,
the extent of the Property class. Thus, this expression selects the instance of Property (if any)
whose identifier equals that given in the request.
2. This is an assignment to the acquisition data attribute for property.
NOTE. acquisition data is an opposite association end owned by the class Property. The fUML
subset does not actually include such associations (fUML requires that all ends of associations are
owned by the association). However, since an association end owned by a class is a structural
feature, it can be written by an add structural feature value action. But, per fUML semantics, no link
is actually created—only the structural feature is set.
} else {
if (request.'property location' -> notEmpty()) {
location = Location -> select loc
dispose
namespace 'Property Management'::'Service Model'::
'Property Management Service Implementation';
} else {
property.'disposition data' = request.'property disposition data';
property.'update status'();
delete
namespace 'Property Management'::'Service Model'::
'Property Management Service Implementation';
} else {
reply = this.'create reply'(request.identifier, property);
property.destroy(); // See Note 1
}
}
Note
1. The expression “property.destroy()” destroys the object property.
retrieve
namespace 'Property Management'::'Service Model'::
'Property Management Service Implementation';
} else {
reply = this.'create reply'(request.identifier, property);
}
}
C.4.1 CollectionClasses::Impl
The CollectionClasses::Impl package is required to contain the classes shown in Figure 11-78. The
Alf implementation given for the package below also includes two additional classes that are used to
factor out common behavior from the collection classes (other than Map). The package is also marked as
a model library, so that it does not automatically import the Alf standard library itself (see Subclause
10.1).
namespace Alf::Library::Collections::CollectionClasses;
@ModelLibrary
package Impl {
C.4.2 CollectionClasses::Impl::CollectionImpl
The abstract CollectionImpl class provides implementations for the operations (other than
toSequence) common to all collection classes other than Map. The actual collection content is expected
to be supplied by the concrete subclasses of CollectionImpl. The CollectionImpl operation method
use abstract methods setContent and toSequence, to be defined in the subclasses, to set and get this
content.
Note that, since the Impl package is stereotyped as a model library, the usual importation of standard
library packages is suppressed. Therefore, the CollectionFunctions package must be explicitly
imported in order to make the collection functions usable without qualification. The collection functions
are imported privately, as required by the rules of Subclause 11.6 for the implementation of collection
classes.
namespace Alf::Library::Collections::CollectionClasses::Impl;
private import
Alf::Library::FunctionBehaviors::Collections::CollectionFunctions::*;
/**
The base concrete implementation for all the standard library collection classes.
*/
abstract class CollectionImpl<T> {
public clear () {
this.setContent(null);
}
C.4.3 CollectionClasses::Impl::OrderedCollectionImpl
The class OrderedCollectionImpl extends CollectionImpl with implementation of additional
operations found in the ordered collection classes (i.e., OrderedSet and List).
namespace Alf::Library::Collections::CollectionClasses::Impl;
private import
Alf::Library::FunctionBehaviors::Collections::CollectionFunctions::*;
/**
The base concrete implementation for the standard library ordered collection
classes
*/
abstract class OrderedCollectionImpl<T> specializes CollectionImpl<T> {
C.4.4 CollectionClasses::Impl::Set
The Set class given below implements the abstract CollectionClasses::Set class. It does this by
defining a content attribute of the appropriate type with unbounded multiplicity. By default, the
attribute is unique and unordered—that is, a set. Operation methods are provided by specializing the
CollectionImpl class.
namespace Alf::Library::Collections::CollectionClasses::Impl;
private import
Alf::Library::FunctionBehaviors::Collections::CollectionFunctions::*;
/**
The concrete implementation of the standard library template Set class.
*/
class Set<T> specializes CollectionImpl<T>, CollectionClasses::Set<T> {
C.4.5 CollectionClasses::Impl::OrderedSet
The OrderedSet class given below implements the abstract CollectionClasses::OrderedSet class. It
does this by defining a content attribute of the appropriate type with unbounded multiplicity. The
C.4.7 CollectionClasses::Impl::List
The List class given below implements the abstract CollectionClasses::List class. It does this by
defining a content attribute of the appropriate type with unbounded multiplicity defined as a sequence
—that is, a nonunique, ordered list. Operation methods are provided by specializing the
OrderedCollectionImpl class.
namespace Alf::Library::Collections::CollectionClasses::Impl;
private import
Alf::Library::FunctionBehaviors::Collections::CollectionFunctions::*;
/**
The concrete implementation of the standard library template List class.
*/
class List<T>
specializes OrderedCollectionImpl<T>, CollectionClasses::OrderedSet<T> {
C.4.8 CollectionClasses::Impl::Queue
The List class given below implements the abstract CollectionClasses::List class. It does this by
defining a content attribute of the appropriate type with unbounded multiplicity defined as a sequence
—that is, a nonunique, ordered list. Operation methods are provided by specializing the
CollectionImpl class. Even though a queue is effectively ordered, it does not provide all the operations
defined for other ordered classes and, therefore, does not specialize the OrderedCollectionImpl class.
namespace Alf::Library::Collections::CollectionClasses::Impl;
private import
Alf::Library::FunctionBehaviors::Collections::CollectionFunctions::*;
/**
The concrete implementation of the standard library template Queue class.
*/
class Queue<T> specializes CollectionImpl<T>, CollectionClasses::Set<T> {
C.4.9 CollectionClasses::Impl::Deque
The Deque class given below implements the abstract CollectionClasses::Deque class. It does this by
extending the Queue implementation class with the additional operations defined for a Deque.
namespace Alf::Library::Collections::CollectionClasses::Impl;
private import
Alf::Library::FunctionBehaviors::Collections::CollectionFunctions::*;
/**
The concrete implementation of the standard library template Deque class.
*/
class Deque<T> specializes Queue<T> {
C.4.10CollectionClasses::Impl::Map
The Map class given below implements the abstract CollectionClasses::List Map. It does this by
storing a set of entries in an attribute. Lookup of entries is implemented in the private indexOf
operation.
namespace Alf::Library::Collections::CollectionClasses::Impl;
private import
Alf::Library::FunctionBehaviors::Collections::CollectionFunctions::*;
/**
The concrete implementation of the standard library template Map class.
*/
class Map<Key, Value> specializes CollectionClasses::Map<Key,Value> {
public clear () {
this.entries = null;
}
<DEFAULT,IN_STATEMENT_ANNOTATION,IN_IN_LINE_ANNOTATION> SKIP : {
" "
| "\t"
| "\f"
}
<DEFAULT> SKIP : {
"\n"
| "\r"
}
/* STATEMENT ANNOTATIONS */
<IN_STATEMENT_ANNOTATION> TOKEN : {
<EOL: ("//" (~["\n","\r"])*)? ("\n" | "\r" ("\n")?)> : DEFAULT
}
<IN_IN_LINE_ANNOTATION> SKIP : {
<("//" (~["\n","\r"])*)? ("\n" | "\r" ("\n")?)> : IN_DOCUMENTATION_COMMENT
}
/* COMMENTS */
<DEFAULT> SKIP : {
<"/**" ~["/"]> : IN_DOCUMENTATION_COMMENT
}
<DEFAULT> MORE : {
"//" : IN_END_OF_LINE_COMMENT
| "/*" : IN_IN_LINE_COMMENT
}
<IN_END_OF_LINE_COMMENT> SKIP : {
<END_OF_LINE_COMMENT: "\n" | "\r" ("\n")?> : DEFAULT
}
<IN_END_OF_LINE_COMMENT> MORE : {
<~[]>
}
<IN_IN_LINE_COMMENT> MORE : {
<~["*"]>
| "*" : IN_IN_LINE_COMMENT_STAR
}
<IN_IN_LINE_COMMENT_STAR> MORE : {
<~["/"]> : IN_IN_LINE_COMMENT
}
<IN_IN_LINE_COMMENT_STAR> SKIP : {
<IN_LINE_COMMENT: "/"> : DEFAULT
}
<IN_DOCUMENTATION_COMMENT> MORE : {
<~["*"]>
| "*" : IN_DOCUMENTATION_COMMENT_STAR
}
<IN_DOCUMENTATION_COMMENT_STAR> TOKEN : {
<DOCUMENTATION_COMMENT: "/"> : DEFAULT
}
<IN_DOCUMENTATION_COMMENT_STAR> MORE : {
<~["/"]> : IN_DOCUMENTATION_COMMENT
/* RESERVED WORDS */
<DEFAULT,IN_STATEMENT_ANNOTATION,IN_IN_LINE_ANNOTATION> TOKEN : {
<ABSTRACT: "abstract">
| <ACCEPT: "accept">
| <ACTIVE: "active">
| <ACTIVITY: "activity">
| <ALL_INSTANCES: "allInstances">
| <ANY: "any">
| <AS: "as">
| <ASSOC: "assoc">
| <BREAK: "break">
| <CASE: "case">
| <CLASS: "class">
| <CLASSIFY: "classify">
| <CLEAR_ASSOC: "clearAssoc">
| <COMPOSE: "compose">
| <CREATE_LINK: "createLink">
| <DATATYPE: "datatype">
| <DEFAULT_: "default">
| <DESTROY_LINK: "destroyLink">
| <DO: "do">
| <ELSE: "else">
| <ENUM: "enum">
| <FOR: "for">
| <FROM: "from">
| <HASTYPE: "hastype">
| <IF: "if">
| <IMPORT: "import">
| <IN: "in">
| <INOUT: "inout">
| <INSTANCEOF: "instanceof">
| <LET: "let">
| <NAMESPACE: "namespace">
| <NEW: "new">
| <NONUNIQUE: "nonunique">
| <NULL: "null">
| <OR: "or">
| <ORDERED: "ordered">
| <OUT: "out">
| <PACKAGE: "package">
| <PRIVATE: "private">
| <PROTECTED: "protected">
| <PUBLIC: "public">
| <RECEIVE: "receive">
| <REDEFINES: "redefines">
| <REDUCE: "reduce">
| <RETURN: "return">
| <SEQUENCE: "sequence">
| <SPECIALIZES: "specializes">
| <SUPER: "super">
| <SIGNAL: "signal">
| <SWITCH: "switch">
| <THIS: "this">
| <TO: "to">
/* NAMES */
<DEFAULT,IN_STATEMENT_ANNOTATION,IN_IN_LINE_ANNOTATION> TOKEN : {
<IDENTIFIER: <IDENTIFIER_LETTER> (<IDENTIFIER_LETTER_OR_DIGIT>)*>
| <#IDENTIFIER_LETTER_OR_DIGIT: <IDENTIFIER_LETTER> | <DIGIT>>
| <#IDENTIFIER_LETTER: ["a"-"z","A"-"Z","_"]>
| <#DIGIT: "0" | <NONZERO_DIGIT>>
| <#NONZERO_DIGIT: ["1"-"9"]>
| <UNRESTRICTED_NAME: "\'" (<NAME_CHARACTER>)+ "\'">
| <#NAME_CHARACTER: ~["\'","\\"] | <ESCAPE_CHARACTER>>
| <#ESCAPE_CHARACTER: "\\" <ESCAPED_CHARACTER>>
| <#ESCAPED_CHARACTER: ["\'","\"","b","f","n","\\"]>
}
/* PRIMITIVE LITERALS */
<DEFAULT,IN_STATEMENT_ANNOTATION,IN_IN_LINE_ANNOTATION> TOKEN : {
<BOOLEAN_LITERAL: "true" | "false">
| <BINARY_LITERAL: ("0b" | "0B") <BINARY_DIGIT> (("_")? <BINARY_DIGIT>)*>
| <#BINARY_DIGIT: ["0","1"]>
| <HEX_LITERAL: ("0x" | "0X") <HEX_DIGIT> (("_")? <HEX_DIGIT>)*>
| <#HEX_DIGIT: <DIGIT> | ["a"-"f","A"-"F"]>
| <OCTAL_LITERAL: "0" (("_")? <OCTAL_DIGIT>)+>
| <#OCTAL_DIGIT: ["0"-"7"]>
| <DECIMAL_LITERAL: "0" | <NONZERO_DIGIT> (("_")? <DIGIT>)*>
| <STRING_LITERAL: "\"" (<STRING_CHARACTER>)* "\"">
| <#STRING_CHARACTER: ~["\"","\\"]>
}
/* PUNCTUATION */
<DEFAULT,IN_STATEMENT_ANNOTATION,IN_IN_LINE_ANNOTATION> TOKEN : {
<LPAREN: "(">
| <RPAREN: ")">
| <LBRACE: "{">
| <RBRACE: "}">
| <LBRACKET: "[">
| <RBRACKET: "]">
| <SEMICOLON: ";">
| <COMMA: ",">
| <DOT: ".">
| <DOUBLE_DOT: "..">
| <COLON: ":">
| <DOUBLE_COLON: "::">
| <ARROW: "->">
| <THICK_ARROW: "=>">
}
/* OPERATORS */
<DEFAULT,IN_STATEMENT_ANNOTATION,IN_IN_LINE_ANNOTATION> TOKEN : {
<ASSIGN: "=">
| <GT: ">">
| <LT: "<">
K.2 Parser
The syntax grammar given below is an LL grammar, that is, a grammar designed for “top down” parsing
(such as recursive descent). A lookahead of only one token is required for most of the grammar. In all
other cases except one, a maximum lookahead of three tokens is required. The parsing of qualified
names with template bindings, however, requires a potentially unbounded lookahead to distinguish the
use of a “<” as an opening bracket of a template binding from its use as a less-than sign.
As discussed in Subclause 8.2, the parsing of a syntactic element with the form of a qualified name
using the dot notation may be ambiguous. In such cases, the grammar below always parses the
potentially ambiguous element as a qualified name (using the non-terminal
“PotentiallyAmbiguousQualifiedName”. If such an element is later disambiguated as a feature
reference, this will also generally require reparsing of the expression containing the ambiguous qualified
name (e.g., a name expression becomes a property access expression and a behavior invocation becomes
a feature invocation).
Finally, the LL form of the grammar given here is considerably simplified by allowing any unary
expression as the left-hand side of an assignment and any primary expression as the operand of an
/***************
* EXPRESSIONS *
***************/
Expression = UnaryExpression ExpressionCompletion
NonNameExpression = NonNameUnaryExpression ExpressionCompletion
NameToExpressionCompletion = ( NameToPrimaryExpression )?
PrimaryToExpressionCompletion
PrimaryToExpressionCompletion = PostfixExpressionCompletion
ExpressionCompletion
ExpressionCompletion = AssignmentExpressionCompletion
| ConditionalExpressionCompletion
/* PRIMARY EXPRESSIONS */
/* LITERAL EXPRESSIONS */
LiteralExpression = <BOOLEAN_LITERAL>
| <DECIMAL_LITERAL>
| <BINARY_LITERAL>
| <OCTAL_LITERAL>
| <HEX_LITERAL>
| <STRING_LITERAL>
| <STAR>
/* NAME EXPRESSIONS */
NameOrPrimaryExpression = PotentiallyAmbiguousQualifiedName
( NameToPrimaryExpression )?
/* THIS EXPRESSIONS */
ThisExpression = <THIS> ( Tuple )?
/* PARENTHESIZED EXPRESSIONS */
ParenthesizedExpression = <LPAREN> Expression <RPAREN>
/* INVOCATION EXPRESSIONS */
Tuple = <LPAREN>
( NamedTupleExpressionList
| ( PositionalTupleExpressionList )?
) <RPAREN>
/* UNARY EXPRESSIONS */
UnaryExpression = PostfixOrCastExpression
| NonPostfixNonCastUnaryExpression
PostfixOrCastExpression = NonNamePostfixOrCastExpression
| NameOrPrimaryExpression
PostfixExpressionCompletion
NonNameUnaryExpression = NonNamePostfixOrCastExpression
| NonPostfixNonCastUnaryExpression
/* ARITHMETIC EXPRESSIONS */
MultiplicativeExpression = UnaryExpression
MultiplicativeExpressionCompletion
MultiplicativeExpressionCompletion
= ( MultiplicativeOperator UnaryExpression )*
MultiplicativeOperator = <STAR> | <SLASH> | <REM>
AdditiveExpression = UnaryExpression AdditiveExpressionCompletion
AdditiveExpressionCompletion = MultiplicativeExpressionCompletion
( AdditiveOperator MultiplicativeExpression)*
AdditiveOperator = ( <PLUS> | <MINUS> )
/* SHIFT EXPRESSIONS */
ShiftExpression = UnaryExpression ShiftExpressionCompletion
ShiftExpressionCompletion = AdditiveExpressionCompletion
( ShiftOperator AdditiveExpression )*
ShiftOperator = <LSHIFT> | <RSHIFT> | <URSHIFT>
/* CLASSIFICATION EXPRESSIONS */
ClassificationExpression = UnaryExpression
ClassificationExpressionCompletion
ClassificationExpressionCompletion
= RelationalExpressionCompletion
( ClassificationOperator QualifiedName )?
ClassificationOperator = <INSTANCEOF> | <HASTYPE>
/* EQUALITY EXPRESSIONS */
EqualityExpression = UnaryExpression
ClassificationExpressionCompletion
EqualityExpressionCompletion = ClassificationExpressionCompletion
( EqualityOperator ClassificationExpression)*
EqualityOperator = <EQ> | <NE>
/* LOGICAL EXPRESSIONS */
AndExpression = UnaryExpression AndExpressionCompletion
AndExpressionCompletion = EqualityExpressionCompletion
( <LOGICAL_AND> EqualityExpression )*
ExclusiveOrExpression = UnaryExpression
ExclusiveOrExpressionCompletion
ExclusiveOrExpressionCompletion
= AndExpressionCompletion
( <XOR> AndExpression )*
InclusiveOrExpression = UnaryExpression
InclusiveOrExpressionCompletion
InclusiveOrExpressionCompletion
= ExclusiveOrExpressionCompletion
( <LOGICAL_OR> ExclusiveOrExpression )*
/* CONDITIONAL-TEST EXPRESSIONS */
ConditionalExpression = UnaryExpression
ConditionalExpressionCompletion
ConditionalExpressionCompletion
= ConditionalOrExpressionCompletion
( <HOOK> Expression <COLON>
ConditionalExpression )?
/* ASSIGNMENT EXPRESSIONS */
AssignmentExpressionCompletion
= AssignmentOperator Expression
AssignmentOperator = <ASSIGN>
| <PLUSASSIGN>
| <MINUSASSIGN>
| <STARASSIGN>
| <SLASHASSIGN>
| <REMASSIGN>
| <ANDASSIGN>
| <ORASSIGN>
| <XORASSIGN>
| <LSHIFTASSIGN>
| <RSHIFTASSIGN>
| <URSHIFTASSIGN>
/**************
* STATEMENTS *
**************/
StatementSequence = ( DocumentedStatement )*
DocumentedStatement = ( <DOCUMENTATION_COMMENT> )? Statement
/* BLOCK */
Block = <LBRACE> StatementSequence <RBRACE>
/* ANNOTATED STATEMENTS */
AnnotatedStatement = <SLASH_SLASH_AT> Annotations <EOL> Statement
Annotations = Annotation ( <AT> Annotation )*
Annotation = <IDENTIFIER> ( <LPAREN> NameList <RPAREN> )?
NameList = Name ( <COMMA> Name )*
/* IN-LINE STATEMENTS */
InLineStatement = <SLASH_STAR_AT> <IDENTIFIER> <LPAREN> Name
<RPAREN> <DOCUMENTATION_COMMENT>
/* BLOCK STATEMENTS */
BlockStatement = Block
/* EMPTY STATEMENTS */
EmptyStatement = <SEMICOLON>
/* IF STATEMENTS */
IfStatement = <IF> SequentialClauses ( FinalClause )?
SequentialClauses = ConcurrentClauses
( <ELSE> <IF> ConcurrentClauses )*
ConcurrentClauses = NonFinalClause ( <OR> <IF> NonFinalClause )*
NonFinalClause = <LPAREN> Expression <RPAREN> Block
FinalClause = <ELSE> Block
/* SWITCH STATEMENTS */
SwitchStatement = <SWITCH> <LPAREN> Expression <RPAREN>
<LBRACE> ( SwitchClause )*
( SwitchDefaultClause )? <RBRACE>
SwitchClause = SwitchCase ( SwitchCase )*
NonEmptyStatementSequence
SwitchCase = <CASE> Expression <COLON>
SwitchDefaultClause = <DEFAULT_> <COLON> NonEmptyStatementSequence
NonEmptyStatementSequence = ( DocumentedStatement )+
/* WHILE STATEMENTS */
WhileStatement = <WHILE> <LPAREN> Expression <RPAREN> Block
/* DO STATEMENTS */
DoStatement = <DO> Block <WHILE> <LPAREN> Expression
<RPAREN> <SEMICOLON>
/* FOR STATEMENTS */
ForStatement = <FOR> <LPAREN> ForControl <RPAREN> Block
ForControl = LoopVariableDefinition
( <COMMA> LoopVariableDefinition )*
LoopVariableDefinition = Name <IN> Expression
( <DOUBLE_DOT> Expression )?
| QualifiedName Name <COLON> Expression
/* BREAK STATEMENTS */
/* RETURN STATEMENTS */
ReturnStatement = <RETURN> Expression <SEMICOLON>
/* ACCEPT STATEMENTS */
AcceptStatement = AcceptClause
( SimpleAcceptStatementCompletion
| CompoundAcceptStatementCompletion )
SimpleAcceptStatementCompletion
= <SEMICOLON>
CompoundAcceptStatementCompletion
= Block ( <OR> AcceptBlock )*
AcceptBlock = AcceptClause Block
AcceptClause = <ACCEPT> <LPAREN> ( Name <COLON> )?
QualifiedNameList <RPAREN>
/* CLASSIFY STATEMENTS */
ClassifyStatement = <CLASSIFY> Expression ClassificationClause
<SEMICOLON>
ClassificationClause = ClassificationFromClause
( ClassificationToClause )?
| ( ReclassifyAllClause )?
ClassificationToClause
ClassificationFromClause = <FROM> QualifiedNameList
ClassificationToClause = <TO> QualifiedNameList
ReclassifyAllClause = <FROM> <STAR>
QualifiedNameList = QualifiedName ( <COMMA> QualifiedName )*
/*********
* UNITS *
*********/
UnitDefinition = ( NamespaceDeclaration )?
( ImportDeclaration )*
( <DOCUMENTATION_COMMENT> )?
StereotypeAnnotations NamespaceDefinition
StereotypeAnnotations = ( StereotypeAnnotation )*
StereotypeAnnotation = <AT> QualifiedName
( <LPAREN> TaggedValues <RPAREN> )?
TaggedValues = QualifiedNameList
| TaggedValueList
TaggedValueList = TaggedValue ( "," TaggedValue )*
/* NAMESPACES */
NamespaceDefinition = PackageDefinition | ClassifierDefinition
VisibilityIndicator = ImportVisibilityIndicator | <PROTECTED>
/* PACKAGES */
PackageDeclaration = <PACKAGE> Name
PackageDefinition = PackageDeclaration PackageBody
PackageDefinitionOrStub = PackageDeclaration
( <SEMICOLON> | PackageBody )
PackageBody = <LBRACE> ( PackagedElement )* <RBRACE>
PackagedElement = ( <DOCUMENTATION_COMMENT> )?
StereotypeAnnotations
ImportVisibilityIndicator
PackagedElementDefinition
PackagedElementDefinition = PackageDefinitionOrStub
| ClassifierDefinitionOrStub
/***************
* CLASSIFIERS *
***************/
/* CLASSES */
ClassDeclaration = ( <ABSTRACT> )? <CLASS> ClassifierSignature
ClassDefinition = ClassDeclaration ClassBody
ClassDefinitionOrStub = ClassDeclaration ( <SEMICOLON> | ClassBody )
ClassBody = <LBRACE> ( ClassMember )* <RBRACE>
ClassMember = ( <DOCUMENTATION_COMMENT> )?
StereotypeAnnotations
( VisibilityIndicator )?
ClassMemberDefinition
ClassMemberDefinition = ClassifierDefinitionOrStub
| FeatureDefinitionOrStub
/* ACTIVE CLASSES */
ActiveClassDeclaration = ( <ABSTRACT> )? <ACTIVE> <CLASS>
ClassifierSignature
ActiveClassDefinition = ActiveClassDeclaration ActiveClassBody
ActiveClassDefinitionOrStub = ActiveClassDeclaration
( <SEMICOLON> | ActiveClassBody )
ActiveClassBody = <LBRACE> ( ActiveClassMember )* <RBRACE>
( <DO> BehaviorClause )?
BehaviorClause = Block | Name
/* DATA TYPES */
DataTypeDeclaration = ( <ABSTRACT> )? <DATATYPE>
ClassifierSignature
DataTypeDefinition = DataTypeDeclaration StructuredBody
DataTypeDefinitionOrStub = DataTypeDeclaration
( <SEMICOLON> | StructuredBody )
StructuredBody = <LBRACE> ( StructuredMember )* <RBRACE>
StructuredMember = ( <DOCUMENTATION_COMMENT> )?
StereotypeAnnotations ( <PUBLIC> )?
PropertyDefinition
/* ASSOCIATIONS */
AssociationDeclaration = ( <ABSTRACT> )? <ASSOC> ClassifierSignature
AssociationDefinition = AssociationDeclaration StructuredBody
AssociationDefinitionOrStub = AssociationDeclaration
( <SEMICOLON> | StructuredBody )
/* ENUMERATIONS */
EnumerationDeclaration = <ENUM> Name ( SpecializationClause )?
EnumerationDefinition = EnumerationDeclaration EnumerationBody
EnumerationDefinitionOrStub = EnumerationDeclaration
( <SEMICOLON> | EnumerationBody )
EnumerationBody = <LBRACE> EnumerationLiteralName
( <COMMA> EnumerationLiteralName )* <RBRACE>
EnumerationLiteralName = ( <DOCUMENTATION_COMMENT> )? Name
/* SIGNALS */
SignalDeclaration = ( <ABSTRACT> )? <SIGNAL> ClassifierSignature
SignalDefinition = SignalDeclaration StructuredBody
SignalDefinitionOrStub = SignalDeclaration
( <SEMICOLON> | StructuredBody )
/* ACTIVITIES */
ActivityDeclaration = <ACTIVITY> Name ( TemplateParameters )?
FormalParameters ( <COLON> TypePart )?
/* FEATURES */
FeatureDefinitionOrStub = AttributeDefinition
| OperationDefinitionOrStub
ActiveFeatureDefinitionOrStub = ReceptionDefinition
| SignalReceptionDefinitionOrStub
/* PROPERTIES */
PropertyDefinition = PropertyDeclaration <SEMICOLON>
AttributeDefinition = PropertyDeclaration ( AttributeInitializer )?
<SEMICOLON>
AttributeInitializer = <ASSIGN> InitializationExpression
PropertyDeclaration = Name <COLON> ( <COMPOSE> )? TypePart
TypePart = TypeName ( Multiplicity )?
TypeName = ( QualifiedName | <ANY> )
Multiplicity = <LBRACKET> ( MultiplicityRange )? <RBRACKET>
( <ORDERED> ( <NONUNIQUE> )?
| <NONUNIQUE> ( <ORDERED> )?
| <SEQUENCE>
)?
MultiplicityRange = ( <DECIMAL_LITERAL> <DOUBLE_DOT> )?
UnlimitedNaturalLiteral
UnlimitedNaturalLiteral = <DECIMAL_LITERAL> | <STAR>
/* OPERATIONS */
OperationDeclaration = ( <ABSTRACT> )? Name FormalParameters
( <COLON> TypePart )? ( RedefinitionClause )?
OperationDefinitionOrStub = OperationDeclaration ( <SEMICOLON> | Block )
RedefinitionClause = <REDEFINES> QualifiedNameList
/* RECEPTIONS */
ReceptionDefinition = <RECEIVE> QualifiedName <SEMICOLON>
SignalReceptionDeclaration = <RECEIVE> <SIGNAL> Name
( SpecializationClause )?