The CONVECS team is pleased to announce
that version 3.14 of the TRAIAN compiler for LNT/LOTOS NT is available.
In October 2023, TRAIAN became part of the CADP toolbox, where it provides a full-fledged compiler front-end for the LNT language, allowing to catch mistakes not detected by the "lightweight" approach of the LNT2LOTOS translator. Recently, TRAIAN 3.13 became part of CADP 2024-d, TRAIAN 3.14 beta-4 became part of CADP 2024-e, and TRAIAN 3.14 beta-9 became part of CADP 2024-f.
TRAIAN 3.14 brings four language changes, twenty-three static-semantics changes, two code-generation changes, one release change, and four bug fixes (see below their description).
The grammar of LNT has been extended to enable channels to be declared with a "raise" attribute. For instance, the EXIT channel is now defined as follows in "lotosnt_predefined.lnt":
channel EXIT is raise () end channelThis attribute indicates that EXIT is a channel dedicated to exceptions. It is possible to declare several such channels, so that the criterion is no longer whether the name of the channel is "EXIT", but whether it has the "raise" attribute. In practice, this change should be invisible to most users.
The TRAIAN reference manual has been updated and a few error messages have been modified accordingly. For instance:
event E declared with channel C instead of EXIT event E has channel C instead of EXIT event E should not have channel EXITbecome:
event E declared with non-"raise" channel C event E has non-"raise" channel C event E should not have "raise" channel EXITSee item 627 in the HISTORY.txt file.
"case ... in var" is deprecated and should be replaced by "case ... var" (3 occurrences found)From now on, such constructs are rejected syntactically, as they have been deprecated since March 2021. LNT programs with such constructs can be updated automatically by invoking "traian_upc" with key 2021-LOTNT-CASE-VAR. See item 638 in the HISTORY.txt file.
From now on, the 3rd option is excluded. To obtain this option, one should now write either X () [Y] or (X) [Y], which is safer and more readable.
Furthermore, TRAIAN now solves the syntactic ambiguity between the 1st and 2nd options by using semantic information gained during the identifier binding phases.
For instance, the following program, which was formerly rejected, is now accepted by TRAIAN:
function F [E : exit] : bool is raise E end function process MAIN [G: any, E : exit] is G (F [E]) -- no more error: variable or function E is -- not defined end process
The error messages have also been enhanced. If X is not a variable and Y is not an event, but a variable, then TRAIAN emits the following error message:
array X is not declaredrather than:
event Y is not declaredSee item 651 in the HISTORY.txt file.
V.{...} with either V.{} or Vand:
V.{X1 -> V1, X2 -> V2, ...} with V.{X1 -> V1, X2 -> V2}Consequently, the former warning of TRAIAN:
superfluous "..." after all fields have been listedhas been removed. See item 657 in the HISTORY.txt file.
channel C is (X1: Nat, X2: Int), (Y1: Int, Y2: Nat), (Z2: Nat, Z1: Int) end channelFrom now on, TRAIAN detects such channel definitions and rejects them with the following error message:
channel profile with identical types already declared at PROG.lnt:12See item 625 in the HISTORY.txt file.
if false then ... ... elsif false then ... while false loop ... for ... while false by ... loop ...TRAIAN emits a new warning:
condition always falseSimilarly, in presence of clauses such as:
if true then ... ... elsif true then ... while true loop ... for ... while true by null loop ...TRAIAN emits a new warning:
condition always trueNote that loops such as "for X := 0 while true by X := X + 1" are meaningful, so that the warning is only emitted if both "while true" and "by null" are present.
Also, new warnings are emitted if dead code follows such clauses. See item 630 in the HISTORY.txt file.
As a consequence of the tighter integration of LNT2LOTOS and TRAIAN, the new messages no longer refer to the changes implemented in TRAIAN 3.3 but to those implemented in LNT2LOTOS (January 2021). The following modifications have been brought:
WARNING: "*" takes priority over "+" since Traian 3.3have been changed to:
WARNING: "*" takes priority over "+" since February 2021since the users of CADP are not expected to know about earlier versions of TRAIAN.
see item #259 of $LNTDIR/HISTORY.txt for more information on the above warning(s)have been changed to:
pragma !update "2021-b" can be used to silence this warningsince the users of CADP are not expected to read the HISTORY.txt file of TRAIAN.
"and" no longer takes priority over "==" since ...Similar warnings have also been suppressed, e.g.:
"and" no longer takes priority over "or" since ... "and" no longer takes priority over "<" since ... "=" no longer takes priority over "+" since ... "or" no longer takes priority over "==" since ...
"+" takes priority over "<" since ... "-" takes priority over "==" since ... "*" takes priority over "+" since ... "OR" takes priority over "==" since ... "xOr" takes priority over "=>" since ... etc.
V1 op V2 op' V3a warning is only emitted when both expressions:
(V1 op V2) op' V3and:
V1 op (V2 op' V3)are correctly typed. If not, TRAIAN assumes that there is no ambiguity on the intentions of the programmer, so that no warning is needed. For instance, the following warnings are no longer displayed:
"+" takes priority over "<" since ... "-" takes priority over "==" since ... "==" takes priority over "and" since ... "<" takes priority over "or" since ...However, certain warnings cannot be removed using type information, e.g.:
"*" takes priority over "+" since ...See item 634 in the HISTORY.txt file.
pragma !... already presentin order to make it more explicit (as was done by LNT2LOTOS):
pragma !... already present for this function pragma !... already present for this type pragma !... already present for this processSee item 635 in the HISTORY.txt file.
variable X is already declared at ...becomes, in processes and functions:
parameter X is already declared at ...
variable X is already declared at ...becomes, in channel definitions:
channel parameter E is already declared at ...
".in" improperly used with "out" parameter Xbecomes:
invalid ".in" qualifier for "out" parameter X
"result" improperly used outside function returning a resultbecomes:
"result" only allowed in functions that return a result
multiple fields X with different types in definition of channel Cbecomes:
field X declared with a different type at ...
constructor function C is already declared at ...becomes:
constructor function C is already declared with the same profile at ...
Also, in many error messages, the adjectives "illegal" and "not defined" have been changed to "invalid" and "not declared", respectively. See item 636 in the HISTORY.txt file.
condition always trueand
condition always falseor
condition always false (behaviour equivalent to "stop")The data flow analysis has been enhanced to consider that nondeterministic assignments with a "where false" condition are equivalent to "stop". Consequently, such assignments trigger new warnings:
unreachable behaviour (dead code) after "stop"Another consequence is that TRAIAN may accept programs that were formerly rejected, because it now ignores more dead code fragments. See item 637 in the HISTORY.txt file.
function F() : bool is if false then null else return true end if -- no more error: function F may terminate without -- returning a value end functionConversely, certain programs that were accepted are now rejected, as TRAIAN detects more infinite loops in functions and more dead code in processes:
function F (in var X : Int) : Int is while true loop if X < 0 then X := X - 1 elsif false then return X end if end loop -- new error: function looping infinitely end function function F() : bool is if false then null else return true end if; return false -- new warning: unreachable instruction (dead code) -- after "return" end functionSee item 639 in the HISTORY.txt file.
channel C is raise (X : NAT) end channelTRAIAN emits the following error message:
limitation: non-empty profile for a "raise" channelThis is a temporary limitation that we expect, with time, to remove, thus allowing exceptions to have parameters. See item 640 in the HISTORY.txt file.
- event "E" occurs twice in "access" - event "E" occurs twice in synchronized events - predefined event "UNEXPECTED" may not occur in "access" - predefined event "i" may not occur in synchronized events - predefined event "UNEXPECTED" may not occur in synchronized eventsSee item 641 in the HISTORY.txt file.
On the one hand, the new version of TRAIAN may now accept programs that were formerly rejected. For instance, a "case" statement that assigns a variable X in all its branches but one branch with a "where false" condition is now accepted, whereas it was rejected with an error message such as:
variable X may be uninitializedOn the other hand, TRAIAN now emits new warnings and error messages about incomplete patterns in "case" instructions and, also, because it detects more infinite loops, e.g.:
process P [PRINT: any] (X: Nat) is case X var Y: Nat in Y where false -> use Y | any -> stop end case; PRINT (true) -- new warning: unreachable behaviour (dead code) after "stop" end process function F (X: Nat) : Bool is loop L in case X var Y: Nat in Y where false -> use Y; break L | any -> null end case end loop; -- new error: function looping infinitely return true end functionSee item 642 in the HISTORY.txt file.
warning: superfluous "alt" with only one branch warning: superfluous "par" with only one branchSee item 644 in the HISTORY.txt file.
F [E -> E1, E -> E2] (...)were either not detected or rejected with an obscure message:
function F called with incorrect profileFrom now, the following message is emitted:
multiple occurrences of event parameter E before "->"See item 647 in the HISTORY.txt file.
warning: empty modulethat is emitted when a module contains no definition of type, channel, function, or process. See item 648 in the HISTORY.txt file.
invalid value 4 for pragma !nat_checkbecomes:
invalid value 4 for pragma !nat_check (0 or 1 expected)
invalid value 0 for pragma !bitsbecomes:
invalid value 0 (less than 1) for pragma !bits
invalid value 1 for pragma !cardbecomes:
invalid value 1 (less than 2) for pragma !card
range lower bound with incorrect typebecomes:
range lower bound -1 is not a constant of type NAT
in pragma !..., C identifier X already definedbecomes:
in pragma !..., C identifier "X" already employed at ...
See item 649 in the HISTORY.txt file.
function F (X: bool, out var Y: bool) : bool is trap E2: exit -> Y := false | E3: exit -> Y := true in if X then raise E3 else raise E2 end if end trap; return Y -- no more error: function F may return without assigning parameter Y end function process P [G: any] (X: bool, out Y: bool) is trap E1: exit -> Y := true | E2: exit -> Y := false | E3: exit -> G (false) in if X then raise E1 else raise E2 end if end trap -- no more error: process P may return without assigning parameter Y end process
G (?X, 12 of Int, ?X)TRAIAN no longer displays:
multiple occurrences of variable X in patternbut displays:
variable X modified in both 1st and 3rd receive offerswhich is more informative.
Also, given the following "case" instruction:
case A, B, C in X, C1 (Y), C2 (X) -> ... ... end caseTRAIAN no longer displays:
multiple occurrences of variable X in patternbut displays:
variable X modified both in 1st and 3rd patternsSee item 653 in the HISTORY.txt file.
variable X is uninitializedand:
variable X may be uninitializedSee item 655 in the HISTORY.txt file.
superfluous "..." after all offers have been listedthat is emitted when an event is used with an ellipsis although all fields of the channel profile for this event are already covered by explicit input or output offers. See item 658 in the HISTORY.txt file.
Also, the configuration and READ_ME files for various editors have been updated so that files with extensions ".fnt" and ".tnt" can be recognized as source C files. See item 628 in the HISTORY.txt file.
#define TRAIAN_BOUND_>_172 1 #define TRAIAN_BOUND_+_173 4that prevented the generated C code to compile properly. From now on, TRAIAN generates correct C code, e.g.:
#define TRAIAN_BOUND_FUNC_172 1 #define TRAIAN_BOUND_FUNC_173 4See item 633 in the HISTORY.txt file.
!comparedby "C:" !implementedby "LOTOS:"for which TRAIAN emitted misleading error messages:
in pragma !compared, invalid C identifier (keyword or standard macro of the C language) in pragma !implementedby, invalid LOTOS identifier (keyword of the LOTOS language)From now on, TRAIAN displays more informative messages:
invalid string "" for pragma !comparedby (not a C identifier) invalid string "" for pragma !implementedby (not a LOTOS identifier)See item 645 in the HISTORY.txt file.
!bits !card !int_bits !nat_bits !nat_inf !nat_sup !num_card !num_bitsare parsed as unsigned integers rather than signed ones. Negative numbers and numbers preceded by a "+" sign are now syntactically rejected. The reference manual of TRAIAN has been updated accordingly to use NATURAL instead of INTEGER for the type of these arguments.
error: too large natural constantwas not appropriate for signed integers, such as the arguments of the !int_inf and !int_sup pragmas. It has been split into two different messages:
limitation: out-of-bound natural constant limitation: out-of-bound integer constantThe use of "limitation" makes it clear that it is not an error in the source program, but rather a limitation of the compiler.
!card 111111111111111111111111111111111111111111no longer triggers a message:
illegal value -954437177 for pragma !cardand terminates the execution of TRAIAN with the UNEXPECTED exception, but triggers a proper error message:
out-of-bound natural constant 1111111111111111111111...
!int_inf 1_0_0 !int_sup 1_0_2are treated like:
!int_inf 100 !int_sup 102whereas they were formerly recognized as:
!int_inf 1 !int_sup 1
See item 646 in the HISTORY.txt file.
function F (in var X1: bool, X2: bool, out Y: bool) is if not (X1) then Y := false end if; while X1 loop L in if X2 then Y := true; break L end if; X1 := false end loop -- Y not initialized if X1 = true and X2 = false end function process P (in var X1: bool, X2: bool, out Y: bool) is for if not (X1) then Y := false end if while X1 by null loop L in if X2 then Y := true; break L end if; X1 := false end loop -- Y not initialized if X1 = true and X2 = false end processSee item 656 in the HISTORY.txt file.
For many years, TRAIAN has been used to develop compilers, including those of the CADP toolbox.
At present, TRAIAN is also part of the CADP toolbox, in which it serves to analyze formal specifications of concurrent systems.
We plan to pursue the progressive unification of the LOTOS NT and LNT
languages, and to increase the co-operation between the LNT2LOTOS and TRAIAN
compilers.
TRAIAN 3.14 can be freely downloaded from the TRAIAN Web Page located at: