This is the developmental release of the forthcoming 4.4.3 release.
Build 210224 adds experimental features to assist with the use of very large specifications. In these cases, the order of the modules passed to the parser and type-checker can have a great effect on the speed of the type-check and initialization. To assist with this, it is possible to create an ".vscode/ordering" file when using VDM VSCode, which contains the order for files to be processed. The order should have the least dependent modules or classes first (things that everything else uses, like libraries) with successively more dependent modules afterwards. To help with the creation of this file, there is a new command plugin (in the
cmd-plugins jar) which adds an "order" command to VDMJ. After loading the specification, the order command will list the optimal order for the files.
> help ... order [filename] - print/save optimal module/class order > order init.order Generating dependency graph Checking for cyclic dependencies Removing link trm -> poi Removing link cal -> poi Removing link cal -> dcm ... Removing link runs -> cal Removed 22 cycles Ordering from startpoints: [emv_other, poi, DBLink, emv_config_cved, emv_config_cmn_map, emv] Order written to init.order >
The saved file can be copied to
.vscode/ordering if you are using VDM VSCode, or it can be used on the VDMJ command line with something like
$(cat init.order) in place of the usual list of filenames passed.
Large specifications also suffer in combinatorial testing because they may take a comparatively long time to initialize. Since a combinatorial test re-initializes the specification between tests, this can significantly slow down their operation. To help with this, build 210224 includes a feature to serialize the initialized state of the specification and use this to restore the state between tests rather than re-calculating it. This can save significant effort with very large specification that have complex initializations, though for very small specifications it is likely to be slower than simply re-calculating the state. To enable the feature, set the property
The latest snapshot release includes some renaming of VDMJ properties. This is to rationalise the (growing) set of names that had been added over the years. The default
vdmj.properties file, which lists all names, is included in the artifacts below.
4.4.3 Build 210211, Initial release (same as 4.4.2-release)
4.4.3 Build 210224, Added "order" command, fixed POs for ext clauses, add cached initialization for traces
4.4.3 Build 210306, Renamed some VDMJ properties.
The latest build artifacts are included below.
Release 4.4.2 adds significant functionality to the LSP/DAP server which supports the VDM VSCode extension.
4.4.2 Build 210113, Initial release.
4.4.2 Build 210202, Various updates from VDM VSCode testing
4.4.2 Build 210211, Final release.
The latest artifacts are available below.
This is the first release to be included in the VS Code Client. It includes changes to the LSP/DAP subsystem to support this, as well as other fixes and improvements in the language engine.
4.4.1 Build 201120, Initial release
4.4.1 Build 210104, Fixed "stop" bug #21 in debugger, move DBGP into a separate module/jar.
4.4.1 Build 210105, Updated vdmjc client for separate DBGP jar. Updated user guide for threads.
4.4.1 Build 210106, Renamed VDMJC to DBGPC and moved documentation.
4.4.1 Build 210107, Added break, trace, list and remove commands to debugging environment, issue #41.
4.4.1 Build 210113, Final release, used in VS Code Client.
The latest assets are attached to this release.
This release adds Language Server Protocol (LSP) and Debug Access Protocol (DAP) support to VDMJ so that it can be driven from any of several UI client that supports these protocols. The changes are being developed and tested in parallel with the VDM extension for VS Code, available here.
There is more detail about how to use LSP itself in the README for the LSP sub-project.
When snapshots are available, they will be published below. Note that all jars within the VDM suite now have the same 4.4.0-SNAPSHOT version, though individual files may be released as bugfix builds (the -YYMMDD suffix).
Released as 4.4.0 on 20/11/20.
Annotations are 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. See AnnotationGuide.pdf for full details.
VDMJ provides some standard annotations, but the intent is that specifiers can create new
annotations and add them to the VDMJ system easily.
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);
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
• 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.
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
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
> 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 > ...
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:
@Override is like the Java annotation of the same name, used in VDM++ functions and operations
@Trace is used to print variable values during execution
@NoPOG is used to suppress PO generation for a section of the specification
@Printf is equivalent to IO'printf, except it can be used in functions as well as operations
@OnFail is the same as
@Printf, but it only produces output if the (boolean) expression after it fails
@Warning is used to suppress specific warning messages
Users are encouraged to write their own annotations. Full details on how to do this are in the AnnotationGuide.pdf.
A new command line option,
-strict has been added to this release, which highlights (with warnings) where a specification is taking advantage of lenient parsing rules. VDMJ does not precisely follow the rules in the grammar in some places - for example, the grammar insists that any module imports appear before exports, but the VDMJ parser will allow them in either order. This causes problems when specifications are ported to other tools, which may follow the grammar more strictly (eg. VDMTools, though that is also lenient in places). Using the
-strict option highlights potential problem areas. The new warnings are as follows:
5022, "Strict: expecting semi-colon between exports" 5023, "Strict: expecting semi-colon between imports" 5024, "Strict: order should be imports then exports" 5025, "Strict: expecting 'exports all' clause" 5026, "Strict: order should be inv, eq, ord" 5027, "Strict: order should be inv, init" 5028, "Strict: expecting semi-colon between traces" 5029, "Strict: unexpected trailing semi-colon"
It is sensible to use the
-strict flag for all new specifications. The warnings that it currently raises will be converted to errors in a subsequent release (though with a
-lenient flag to be backward compatible).
4.3.0 Build 190217, Initial release
4.3.0 Build 190306, Added -strict flag and parser warnings
4.3.0 Build 190309, Corrected a bug with trace expansion
4.3.0 Build 190314, Fixed type bind expansion with invariants and annotation expression parsing
4.3.0 Build 190318, Fixed type checking errors for operation return values
4.3.0 Build 190319, Fixed error with mixed sets of ordered and non-ordered types
4.3.0 Build 190320, Improved type checking for polymorphic types
4.3.0 Build 190619, Fix annotated expression parsing to bind tightly, added
@OnFail to annotation2
4.3.0 Build 190704, Fix warning in multiple binds of the same name
4.3.0 Build 190919, Fix PO for non-nil ordered comparison expressions
4.3.0 Build 190927, Fix expression annotation parsing of applicators
4.3.0 Build 191001, Fix bug with type imports not matching exports
4.3.0 Build 191015, Fix bug regarding taking nat values of 0 state variables
4.3.0 Build 191110, Fix bug with recursive record types and change POM to Java 1.7
4.3.0 Build 191117, Fix bug with specification statement parsing
4.3.0 Build 191128, Fix bug with high precision literals (-P build only)
4.3.0 Build 191130, Added better stack overflow handling
4.3.0 Build 191206, Improved annotation parser error detection
4.3.0 Build 191212, Correctly identify reserved prefixes (inv_, pre_ etc) as errors
4.3.0 Build 191216, Add warning for complex polymorphic type usage
4.3.0 Build 191217, Corrected some precision settings for HP library functions
4.3.0 Build 191218, Added #ifndef processing
4.3.0 Build 191223, Added PO generation for mutually recursive functions
4.3.0 Build 200103, Correction to mutual recursion detection/POs for VDM++
4.3.0 Build 200106, Improved exit detection and recursive loop efficiency
4.3.0 Build 200107, Correct seq comprehensions to allow type binds
4.3.0 Build 200315, Add defence to "eq" function for nil values
4.3.0 Build 200401, Small changes to support LSP/DAP server
4.3.0 Build 200426, Added
@Warning annotation and update Guide
4.3.0 Build 200504, Small fixes for LSP
4.3.0 Build 200505, Fix for stop/quit actions while debugging.
4.3.0 Build 200512, Some LSP fixes.
4.3.0 Build 200515, Moved @OnFail to annotations, fixed IO library, add commands to LSP
4.3.0 Build 200516, Added set and quit commands
4.3.0 Build 200604, Enable breakpoints during initialization, including via LSP
4.3.0 Build 200605, Added init command to LSP
4.3.0 Build 200610, Fixed a bug with recursive
4.3.0 Build 200611, Updated annotations jars
4.3.0 Build 200618, Added "script" command and updated breakpoint handling and User Guide
4.3.0 Build 200711, Tidy visitor framework and add section to Design Spec
4.3.0 Build 200804, Complete tidy of visitor framework.
4.3.0 Build 200810, Convert getAllValues and instantiate method to visitors.
4.3.0 Build 200813, Fixed bug #27, error in RecordValue's compareTo.
4.3.0 Build 200828, Fixed bug #26, stack overflow with recursive type resolutions.
4.3.0 Build 200907, Fixed bug #28, issuing warnings for op calls in let statements.
4.3.0 Build 201004, Fixed bug #29, warning for function value comparisons.
4.3.0 Build 201008, Added vdmj.mappingpath for annotations and added source jar generation to POM.
4.3.0 Build 201023, Correct PO bug for return statements with no expression argument.
4.3.0 Build 201109, Final release of 4.3.0 - moved all jars to 4.3.0(-P)
(Only the last 5 build jars will be retained)
This release contain the changes for RM42, which makes changes to measure clauses. This is also the first release that contains no new Fujitsu IPR.
Measure clauses can now contain a simple expression, using the same parameter variables as the main function, very much like a precondition. Such expressions also cause a function to be created, called measure_f (similar to the creation of pre_f). This function will have the same parameters as the main function, but return a nat or nat tuple, depending on the type of the measure expression.
For example, a measure can now be written as follows:
sum: seq of nat -> nat sum(s) == if s =  then 0 else hd s + sum(tl s) -- measure m; -- measure can be a function measure len s; -- or the expression can now be added inline m: seq of nat -> nat m(s) == len s;
If you use an inline measure, a function is created:
> env sum = (seq of (nat) -> nat) m = (seq of (nat) -> nat) measure_sum = (seq of (nat) +> nat) > p measure_sum([1,2,3]) = 3 Executed in 0.016 secs. > p sum([1,2,3]) = 6 Executed in 0.007 secs.
If you have a complex recursive function that you have not yet written a measure for, or that cannot sensibly have a measure defined, you can suppress the warning by defining a measure as "is not yet specified":
sum: seq of nat -> nat sum(s) == if s =  then 0 else hd s + sum(tl s) measure is not yet specified; -- suppress warning about missing measure
4.2.0 Build 180125, Initial release
4.2.0 Build 180126, Correction for type check of subtractions
4.2.0 Build 180317, Fix for lambda values with polymorphic types
4.2.0 Build 180405, Correction for ext rd/wr name/scope lookups
4.2.0 Build 180608, Small correct to POs with old variable identifiers
4.2.0 Build 180705, Experimental annotations feature (see the -annotations jar)
4.2.0 Build 180721, Added extra -verbose output and optimized initialization
4.2.0 Build 181106, Corrected narrow_ execution and reserved word detection
4.2.0 Build 181110, Absorb ContextExceptions during union value conversions
4.2.0 Build 181114, Correct VDMJC Manifest to use the right main class.