Annotations Guide Annotation

User Manual:

Open the PDF directly: View PDF PDF.
Page Count: 7

DownloadAnnotations Guide Annotation
Open PDF In BrowserView PDF
VDMJ Annotations Guide

Date: 15/02/19

VDMJ Annotations Guide
0.

Table of Contents
1. Overview...................................................................................................................................... 1
2. Syntax.......................................................................................................................................... 1
3. Location....................................................................................................................................... 2
4. Tool Effects.................................................................................................................................. 2
5. Loading and Checking................................................................................................................. 2
6. Standard Annotations.................................................................................................................. 4
6.1. @Override........................................................................................................................... 5
6.2. @Trace................................................................................................................................ 5
6.3. @NoPOG............................................................................................................................ 5
6.4. @Printf................................................................................................................................ 5
7. Creating New Annotations........................................................................................................... 6

1.

Overview
Annotations were introduced in VDMJ version 4.3.0 as a means to allow a specifier to affect the tool’s
behaviour without affecting the meaning of the specification. The idea is similar to the notion of
annotations in Java, which can be used to affect the Java compiler, but do not alter the runtime
behaviour of a program.
VDMJ provides some standard annotations, but the intent is that specifiers can create new
annotations and add them to the VDMJ system easily.

2.

Syntax
Annotations are added to a specification as comments, either block comments or one-line comments.
This is so that other VDM tools will not be affected by the addition of annotations, and emphasises the
idea that annotations do not alter the meaning of a specification.
An annotation must be present at the start of a comment, and has the following default syntax:
‘@’, identifier, [ ‘(‘, expression list, ‘)’ ]
So for example, an operation in a VDM++ class could be annotated as follows:
class A
operations
-- @Override
public add: nat * nat ==> nat
add(a, b) == ...
Or the value of variables can be traced during execution as follows:
functions
add: nat * nat +> nat
add(a, b) ==
/* @Trace(a, b) */ a + b;

Copyright © Nick Battle 2018

Page 1 of 7

VDMJ Annotations Guide

3.

Date: 15/02/19

Location
Annotations are always located next to another syntactic category, even if they do not affect the
behaviour or meaning of that construct. In the examples above, the @Override annotation applies to
the definition of the add operation, and the @Trace annotation applies to the expression a+b.
Specific annotations may limit where they can be applied (for example, @Override only makes sense
for operations and functions in VDM++ specifications), but in general annotations can be applied to the
following:

•

To classes or modules.

•

To definitions within a class or module.

•

To expressions within a definition.

•

To statements within an operation body.

In each case, the annotation must appear in a comment, by itself, before the construct concerned.
Multiple annotations can be applied to the same construct, and may be interleaved with other textual
comments, but each annotation must appear in its own comment.

4.

Tool Effects
Annotations can be used to affect the following aspects of VDMJ's operation:

•

The parser (for example) to enable or disable new language features.

•

The type checker (for example) to check for overrides or suppress warnings

•

The interpreter (for example) to trace the execution path or variables' values

•

The PO generator to (for example) skip obligations for an area of specification.

Note that none of these examples affect the meaning of the specification, only the operation of the
tool. Although it would be possible to create an annotation to affect a specification's behaviour, this is
strongly discouraged.

5.

Loading and Checking
A global flag can be set by an "-annotations" command line argument, or the "set" command. This flag
controls whether the comments in a specification are parsed for annotations. It defaults to false, so
unless the command line switch or set command is used, no annotation processing will be performed.
If the set command is used from within VDMJ, the specification must be reloaded to parse the
comments:
> set
Preconditions are enabled
Postconditions are enabled
Invariants are enabled
Dynamic type checks are enabled
Pre/post/inv exceptions are disabled
Measure checks are enabled
Annotations are disabled
> set annotations on
Specification must now be re-parsed (reload)
> reload
> ...

When annotations are enabled, comments are processed as follows by the parser:

Copyright © Nick Battle 2018

Page 2 of 7

VDMJ Annotations Guide

Date: 15/02/19

•

All comments that precede class/modules, definitions, expressions and statements are
collected by the lexical analyser and added to the corresponding AST node by the parser.

•

The parser checks the comments in an annotated node, looking for those that start with
@.

•

Each comment that looks like an annotation is used to attempt to load a Java class called
ASTAnnotation from a configurable classpath. If the class cannot be found, the
comment containing the annotation is silently assumed to coincidentally contain something
that is a valid annotation syntax, but which is not actually an annotation - like using
@NickBattle to refer to a person by their Twitter handle.

•

For the annotation classes that load successfully, the parser instantiates each annotation, and
calls it to parse the rest of the comment. By default, this will parse an optional list of
expressions between brackets, but each annotation can override the "parse" method to
handle its own argument syntax.

•

An "astBefore" method on the annotations is called, passing the SyntaxReader that is
currently processing the specification. This allows the annotation to affect the parse of the
syntactic element that follows the annotation.

•

The parser parses the element following the comments using the SyntaxReader.

•

The parser calls an "astAfter" method on the annotations after the parse of the element,
passing the SyntaxReader and the parsed AST node, to allow the annotation to affect the
result of the parse or undo any changes it made to the SyntaxReader.

•

The parse then continues as normal.

Note that so far there has been no checking of the annotation itself, other than its syntax.
If VDMJ correctly parses an entire specification, it next performs type checking. This is done by
converting the tree of AST objects into an equivalent tree of TC objects. This includes annotations that
are attached to AST nodes - ASTAnnotation objects are converted to TCAnnotation
objects, loaded from the same classpath, which contain code to type check the annotation itself as
well as code which may affect the type check of the annotated element.
Type checking proceeds as follows:

•

When the TC tree is created, ASTAnnotation objects from the parse are converted to
TCAnnotation objects.

•

When the type checker starts, it calls a static "doInit" method on all loaded TC annotations.
This allows them to reset or set up any persistent data that they require.

•

Before the type check of an annotated element, the type checker calls the "tcBefore" method
of annotations attached to the node, passing the TC node of the element and the Environment
list.

•

The type check of the annotated element then proceeds as normal.

•

After the type check, the "tcAfter" method of the annotations is called, passing the TC node
and Environment as before, but also passing the TCType of the checked node.

The annotation typically uses the "tcBefore" method to type check its arguments (if necessary) and
check anything it needs to check about the annotated TC node. For example, the @Trace annotation
checks that its arguments are simple variable identifiers that are in scope; and the @Override
annotation checks that there are no arguments, that the dialect is VDM++, that the definition
annotated is an operation or function and that there is a superclass that has a definition which is being
overridden by the annotated element.
After the type checking phase, if there are no errors, VDMJ will normally create a tree for the
Copyright © Nick Battle 2018

Page 3 of 7

VDMJ Annotations Guide

Date: 15/02/19

interpreter: TC classes are converted to IN classes, and this includes annotations. Annotations which
apply to classes/modules and definitions do not affect the interpreter, but those that apply to
statements and expressions do (since these elements are "executed").
Execution proceeds as follows:

•

When the IN tree is created, TCAnnotation objects are converted to
INAnnotation objects.

•

When the interpreter is initialised, it calls a static "doInit" method in all loaded IN annotations.
This allows them to reset or set up any persistent data that they require.

•

When an annotated INStatement or INExpression is executed, the evaluation first calls the
"inBefore" method of the annotations, passing the statement or expression and the runtime
Context stack.

•

The statement or expression is then evaluated as normal.

•

The evaluation then calls an "inAfter" method on the annotations, passing the statement or
expression, the runtime Context and the Value from the execution. The annotation cannot
affect the return value.

•

Finally the return value is returned as usual and the overall evaluation proceeds as normal.

The inBefore and inAfter methods allow annotations that affect the interpreter to either intervene
before the annotated element is evaluated or to look at the result after its execution (or both).
If PO generation is required, the TC tree is used to generate a tree of PO objects, including
POAnnotation classes. Proof obligation generation then proceeds as follows:

•

When the PO tree is created, TCAnnotation objects are converted to
POAnnotation objects.

•

When PO generation starts, it calls a static "doInit" method in all loaded PO annotations. This
allows them to reset or set up any persistent data that they require.

•

Before any annotated class/module, definition, statement or expression is processed by the
PO generator, the "poBefore" method of the annotations is called, being passed the
POContextStack and the PO node concerned.

•

PO generation of the PO node then proceeds as normal.

•

After the PO generation, the "poAfter" method of the annotations is called, passing the
POContextStack, the PO node and the ProofObligationList generated by the node. These can
be modified by the "poAfter" method - for example, the @NoPOG annotation clears the
obligation list.

Note that the same annotation (that is, one @Name comment in the source) can affect all four areas
of VDMJ operation, though to do so it needs to define code in the AST, TC, IN and PO trees. If an
annotation affects the type checker, but not (say) the interpreter, the TC-IN mapping for the annotation
should map TCAnnotation to INNullAnnotation, which does nothing. The same principle
applies to other unused analysis mappings; all annotations must define ASTAnnotation.

6.

Standard Annotations
VDMJ includes some standard annotations. They are provided in a separate jar file which needs to be
on the classpath when VDMJ is started. If the jar is not on the classpath, annotations will be silently
ignored.
The standard annotations perform the following processing:
Copyright © Nick Battle 2018

Page 4 of 7

VDMJ Annotations Guide

6.1.

Date: 15/02/19

@Override
This is very similar to the Java @Override annotation, which is used to verify that a Java method
overrides a superclass method, raising an error if not. In VDMJ, the override applies to operations or
functions in a VDM++ class.
The typecheck of the annotation (in the TCOverrideAnnotation "tcBefore" methods) verifies that the
dialect is VDM++, that the annotation has no arguments, and that it is applied to either an operation or
a function definition. Lastly, if there is no "inherited" definition that this definition overrides, an error is
raised.
Error 3363: Definition does not @Override superclass in 'A' (test.vpp) at line 3:9

The annotation has no effect on the interpreter or the PO generator.

6.2.

@Trace
The @Trace annotation is intended to trace the flow of control in the interpreter, either to note that a
particular point in the execution has been reached, or to log the values of variables at that location.
The typechecker checks (in the TCTraceAnnotation "tcBefore" methods) that the annotation is applied
to a statement or an expression only. The check also makes sure that any arguments supplied are
simple variable names and refer to variables that are in scope.
When the interpreter is running, the INTraceAnnotation "inBefore" method either just prints out the
current location to stderr, or it prints the location and " = " for each argument (ie. each
variable name traced). For example, the specification in section 2 produces the following:
> p add(1,2)
Trace: in 'A' (test.vdm) at line 9:13, A`a = 1
Trace: in 'A' (test.vdm) at line 9:13, A`b = 2
= 3
Executed in 0.007 secs.

The annotation has no effect on the execution values or the PO generator.

6.3.

@NoPOG
The @NoPOG annotation is intended to suppress PO generation over a region of the specification. It
can be applied to a class/module, a definition, a statement or an expression.
The typechecker (the TCNoPOGAnnotation "tcBefore" methods) just checks that the annotation has
no arguments passed.
Error 3361: @NoPOG has no arguments in 'A' (test.vdm) at line 9:13

The PO generator (the PONoPOGAnnotation "poAfter" methods) clear the list of proof obligations
generated for the annotated element (class/module, definition, statement or expression).
The annotation has no effect on the interpreter.

6.4.

@Printf
The @Printf annotation is almost identical to the IO`printf library operation, except that as an
annotation it can be used in functions as well as operations, and the arguments do not have to be
presented as a sequence literal.

Copyright © Nick Battle 2018

Page 5 of 7

VDMJ Annotations Guide

Date: 15/02/19

The typecheck (the TCPrintfAnnotation "tcBefore" methods) checks that the annotation has a string as
its first argument.
Execution of the annotation (the INPrintfAnnotation "inBefore" methods) evaluate the arguments and
then pass the Values generated to System.out.printf.
Note that, as with IO`printf, the format string can only contain %s converters, even if the values being
printed are numeric.

7.

Creating New Annotations
Creating new user annotations is a matter of doing the following:

•

Write a new ASTAnnotation class that extends ASTAnnotation. Annotations that don't
affect the parse do not have to implement any methods; there are "astBefore" and "astAfter"
methods that will be called during the parse, if required (see above).

•

Write TC, IN and/or POAnnotation classes that extend TCAnnotation etc. and add the
checking and functionality that you require in the before/after methods.

•

Create the mapping file lines that map the new classes for AST-TC, TC-IN and TC-PO. For
example to add two new annotations called @Notice and @Classic, produce an asttc.mappings file like this:
package annotations.ast to annotations.tc;
map ASTNoticeAnnotation{name, args} to TCNoticeAnnotation(name, args);
map ASTClassicAnnotation{name, args} to TCClassicAnnotation(name, args);

•

Put the new classes and the necessary mapping files on the classpath when VDMJ is
executed. This is easily done by putting them in a jar file, with the mapping file(s) at the top
level. Use the property vdmj.annotations to set the classpath for the annotation classes,
unless you use the standard annotations.ast package for them.

•

Add @Name comments to your specification :-)

Note that VDMJ is issued with @Override, @Trace and @NoPOG annotations in a separate
"annotations" jar. This contains the classes and mapping file extracts required for the standard
annotations. The source (in GitHub) may be a useful resource for producing new annotations. The
layout of the jar is as follows:

Copyright © Nick Battle 2018

Page 6 of 7

VDMJ Annotations Guide

Date: 15/02/19

Copyright © Nick Battle 2018

Page 7 of 7



Source Exif Data:
File Type                       : PDF
File Type Extension             : pdf
MIME Type                       : application/pdf
PDF Version                     : 1.5
Linearized                      : No
Page Count                      : 7
Language                        : en-GB
Title                           : Annotations Guide
Creator                         : Writer
Producer                        : LibreOffice 6.1
Create Date                     : 2019:02:15 12:36:48Z
EXIF Metadata provided by EXIF.tools

Navigation menu