Annotations
Annotations can be added to elements of a CIF specification, to annotate them with extra structured information. Tools that take CIF specifications as input can process the annotations that are attached to elements of the specification, and use the supplied information. Different tools may support different annotations. For the tools in the CIF toolset, the tool documentation indicates for each tool which annotations it supports and how it uses them.
For basic information on annotations, see the language tutorial. For a complete list of the annotations that are bundled with CIF, see the built-in annotations overview.
Syntax
Annotations are optional. If specified, annotations are indicated by a regular annotation name (for most elements of specifications) or double at-sign annotation name (for some elements of specifications). See below for further details on which elements require which kind of annotation name.
Optionally, the annotation may have arguments. If the annotation has arguments, these are put between parentheses, (
and )
. Parentheses may be used if there are no arguments, but this is not recommended. Multiple arguments are separated by commas. An extra comma may optionally follow the last argument, which can make it easier to comment out arbitrary arguments, while still maintaining a valid model.
Each argument consists of an optional name and a mandatory value. If both a name and a value are provided, they are separated by a :
sign. If the argument has a name, it is either a CIF identifier or a CIF relative name. If the argument name is an identifier that is a CIF keyword, it needs to be escaped by prefixing it with a $
sign. Similarly, identifiers within relative names need to be escaped as well. For instance, argument name automaton
needs to be escaped as $automaton
, and argument name some.automaton
needs to be escaped as some.$automaton
. The value of the argument is a CIF expression.
As an example of the syntax, consider the following input variable annotated with 7 annotations:
@anno
@some:anno
@anno1()
@anno2(arg: 3, false)
@anno3($input: true)
@anno4(some_arg: 3, some.other.arg: [123, 467])
@anno5(
arg1: -sqrt(2),
arg2: 3 * 9,
arg3: "some text",
)
input bool x;
Some observations:
The first three annotations do not have any arguments, the other four do.
The arguments have values of various types.
For
anno2
, the first argument is namedarg
, while the second argument is unnamed.For
anno3
, theinput
argument name is escaped to$input
asinput
is a keyword.For
anno4
, the second argument uses a relative name as argument name.For
anno5
, the first and second argument have a computation as value.For
anno5
, there is a comma after each argument, including after the last argument. This makes it easy to later comment out any of the three arguments, or add an extra argument without having add an extra comma.
Placement
Annotations are placed before the elements that they annotate. Here is an example, where an input variable is annotated with an annotation without arguments:
@anno
input bool x;
For a specification, the annotations must be before any other elements of the specification. Here is an example, where the specification with the annotated input variable is extended with two annotations on the specification itself:
@@anno1(arg1: 5)
@@anno2(arg2: "some text")
@anno
input bool x;
Annotations are only supported for the following elements in CIF specifications. Most require regular annotation names, while annotations on specifications and annotations on elements of locations require double at-sign annotation names:
Element | Annotation name |
---|---|
Algebraic parameters |
Regular |
Algebraic variables |
Regular |
Automata |
Regular |
Automaton definitions |
Regular |
Automaton instantiations |
Regular |
Constants |
Regular |
Continuous variables |
Regular |
Discrete variables |
Regular |
Edges |
Double at-sign |
Enumeration literals |
Regular |
Enumerations |
Regular |
Events |
Regular |
Function parameters |
Regular |
Function variables |
Regular |
Functions |
Regular |
Group definitions |
Regular |
Group instantiations |
Regular |
Groups |
Regular |
Input variables |
Regular |
Invariants |
Regular (for invariants in components) |
Locations of automata |
Regular |
Specifications |
Double at-sign |
Type declarations |
Regular |
Constraints
The following general constraints apply to all annotations:
Annotations are optional.
An element of the specification may have multiple annotations.
If an element has multiple annotations, different annotations can be put in any order.
In case a single element is annotated with the same annotation multiple times, then the order of these annotations may be relevant, although this could differ per annotation.
Each named argument of an annotation must have a different name. An annotation may also have any number of unnamed arguments.
The order of the arguments of an annotation is not relevant. That is, if the arguments are re-ordered, then the annotation still has the same meaning.
Each annotation must be registered. When registering an annotation, an annotation provider is registered with it:
If an annotation is used in a specification, but is not registered, a warning will indicate the unregistered annotation. If a tool supports an annotation, it or one of its dependencies should register the annotation. Hence, if an annotation is not registered, it will likely be ignored by all available tools.
Annotations are an extension mechanism, and anyone can define and register their own annotations. Different CIF installations may therefore have different registered annotations. A CIF specification may thus have a warning in one installation, if the annotation is for instance not registered in that installation, while in another installation the annotation does not have a warning, as there it is registered.
If an annotation is registered, it must be properly registered and its annotation provider must be properly implemented. See below for details on annotation providers.
Each annotation provider may impose additional constraints on the annotation it handles:
An annotation and its arguments must satisfy any additional constraints imposed by the corresponding annotation provider.
An annotation provider could for instance limit the elements that may be annotated with the annotation, require all elements of a certain type to be annotated if at least one of them is annotated, or only allow a single such annotation on each annotated element. It could also constrain certain arguments, or combinations of arguments, to be mandatory or optional, or require them to be named or unnamed. Furthermore, it could require arguments to have values of a certain type, to be statically evaluable, and so on. Different people could define the same annotation in different ways, such that their own installations interpret that annotation differently and impose different constraints for it. Hence, a specification with such annotations may be valid in one installation, and invalid in another.
Annotations are an extension mechanism, and anyone can define and register their own annotations. Different CIF installations may therefore have different annotation providers for the same annotation, which may interpret the annotation differently and may impose different constraints for it. Hence, a specification with such annotations may be valid in one installation, and invalid in another.
Naming annotations
Annotations are an extension mechanism, and anyone can define and register their own annotations. Without rules, different people may define the same annotation in different conflicting ways. Therefore, we list some guidelines for naming of annotations. These guidelines are not strict rules and likely will not prevent all issues, but adhering to them will likely at least reduce such issues.
Consider the following guidelines:
Name an annotation based on the conceptual information it represents, not on how it is used. The annotation can then be reused for other uses. This avoids having multiple annotations with the same information for different uses.
Avoid naming an annotation after a specific tool that uses it. The annotation can then be reused by other tools. This avoids having multiple annotations with the same information or purpose for different tools.
Annotations are given a name that is as short as possible, to make it easier to write them. For instance,
doc
for a documentation annotation, rather thandocumentation
.By default, annotation names consist of only a single identifier. If the annotation is specific to a certain purpose, and chances are that similarly named annotations will be introduced in the future, leading to naming conflicts, the annotation name can be scoped. For instance, for annotations related to linking CIF specifications to Programmable Logic Controllers (PLCs), the annotation names may be prefixed with
plc
. For instance,plc:input
could be the name of a PLC input annotation. This allows otherinput
annotations for different purposes to be added as well.More than two levels can be used in annotation names if needed to distinguish the annotations and ensure they are unique.
Annotation names are ideally lower case, consisting of multiple parts separated by colons, rather than having parts that consist of multiple words. For instance, use
plc:input
rather thanplcInput
orplc_input
.If you add a custom annotation, that is not a built-in annotation delivered along with CIF itself, start the annotation with your company name. This prevents conflicts with built-in annotations, and with annotations provided by other companies. For instance, use
<company_name>:some:anno
.
Annotation providers
Annotations can be registered using the org.eclipse.escet.cif.annotations
extension point, provided by the org.eclipse.escet.cif.typechecker
plugin. In your own plugin, to register an annotation:
Open the plugin’s manifest (
META-INF/MANIFEST.MF
file).Navigate to the Extensions tab.
Click the Add button.
Uncheck the Show only extension points from the required plug-ins checkbox.
Select org.eclipse.escet.cif.annotations from the list and click Finish.
If and when asked whether to add the
org.eclipse.escet.cif.typechecker
plugin as a dependency, click Yes.On the Extensions tab, a dummy org.eclipse.escet.cif.annotations entry is automatically added, and it is selected.
Click Show extension point description for more information on how to properly use the extension point.
You can edit the extension on the Extensions tab using the UI, or navigate to the
plugin.xml
tab of the manifest editor and edit it there textually.
A proper extension to register an annotation will look something like this:
<extension
point="org.company.cif.annotations">
<provider
annotationName="some:thing"
class="org.company.cif.annotations.SomeThingAnnotationProvider"
plugin="org.company.cif.annotations">
</provider>
</extension>
Some additional constraints must be adhered to:
At most one annotation provider must be registered for each annotation name.
If an annotation is registered, it must specify an annotation provider. It must indicate the plugin where the provider is located as well as the Java class that implements it.
If an annotation is registered, the registered annotation provider class must exist within that plugin, and the CIF type checker must be able to find and load it.
If an annotation is registered, the registered annotation provider class must extend the
org.eclipse.escet.cif.typechecker.annotations.AnnotationProvider
class. TheAnnotationProvider
class has additional information and requirements. Consult its JavaDoc for the details.