TRAIAN 3.9 released on February 28, 2023



The CONVECS team is pleased to announce that version 3.9 of the TRAIAN compiler for LOTOS NT is available.

Release Notes

TRAIAN 3.9 has been prepared by Hubert Garavel, Frederic Lang, and Wendelin Serwe. It was released four months after version 3.8 of TRAIAN.

With TRAIAN 3.9, the convergence between LOTOS NT and LNT is nearly complete. Measured on a test suite of 13,500+ correct LNT programs totalling more than 9 million non-blank lines of LNT code, TRAIAN 3.9 syntactically accepts 100% of these programs (whereas TRAIAN 3.8 accepted 97.4% of them) and semantically accepts 89.3% of them at the moment (this percentage is expected to increase in the near future).

For many years, TRAIAN has been used to develop compilers, including those of the CADP toolbox. At present, it is also intensively used to check LNT specifications of concurrent systems, allowing to catch mistakes not detected by the "lightweight" approach of the LNT2LOTOS translator.

TRAIAN 3.9 brings twelve language changes, ten static-semantics changes, seven compiler changes, two release changes, and four bug fixes (see below their description).




Language Changes

TRAIAN 3.9 introduces various changes to the LOTOS NT language in order to further align it with LNT language. The LOTOS NT Reference Manual and the demo examples have been updated to reflect these changes.
  1. The LOTOS NT grammar was extended to accept process calls of the form "P ()" (in addition to calls of the form "P", which were already supported), for those processes P without parameters. See item 447 in the HISTORY.txt file.

  2. The LOTOS NT grammar was extended to accept (constructor or non-constructor) function calls of the form "F ()", for functions F without parameters. See item 448 in the HISTORY.txt file.

  3. The syntax of LOTOS NT "special" identifiers was extended to allow the "#" character. For instance, the following function definition is now permitted in LOTOS NT:
       function # (x: Nat) : Nat is
          return x + 1
       end function
    
    See item 455 in the HISTORY.txt file.

  4. The syntax of LOTOS NT was extended: from now on, tabulations can be used directly in character and string values (in addition to the escape notation "\t"). See item 456 in the HISTORY.txt file.

  5. The syntax of LOTOS NT expressions was modified to make them safer and more readable. It is still allowed to invoke a unary operator without parentheses if this operator has a special identifier (e.g., "#", "-", "%%", etc.) but it is now forbidden to invoke several such unary operators in sequence without parentheses.

    For instance, the following code fragment "F1 F2 V" (where F1 and F2 are special unary operators and V an expression) is no longer accepted, and should be written either "F1 (F2 V)" or "F1 (F2 (V))". For instance, "- * # P" must now be written "- (* (#P))".

    It is also forbidden to mix, without parentheses, a unary operator, which is a prefix notation, and the "of" operator, which is a postfix notation. Concretely, "F V of T" is now rejected as ambiguous, and should be written either "(F V) of T" or "F (V of T)". This enables one to better distinguish between, e.g., "(- 128) of BYTE" and -(128 of BYTE). See item 462 in the HISTORY.txt file.


  6. The syntax of LOTOS NT value expressions was modified to forbid invoking several unary operators in sequence without parentheses. For instance, the following code fragments are no longer permitted:
      PRINT (- -1)
      PRINT ((- -1) of bool)
    
    From now on, one should write:
      PRINT (- (-1))
      PRINT ((- (-1)) of bool)
    
    which is more readable and better expresses the user's intent. See item 463 in the HISTORY.txt file.

  7. The syntax of LOTOS NT patterns was simplified to make it more readable. From now on, the following restriction is in effect: if P is a pattern and F is a unary operator, it is no longer allowed to write "F P": parentheses are required, i.e., "F (P)". For instance, "%u" should now be written "% (u)".

    Note that such parentheses are not required between unary "+" or unary "-" and numeric constants to obey longstanding mathematical traditions.

    Also, the following pattern "X * any T + Y", which was formerly accepted and parsed as "(X * any) T (+ Y)", is now rejected with a syntax error: "(" is inserted before "Y". We believe that the new behaviour is more intuitive and avoids confusion.

    Because of this change, some correct LOTOS NT programs may become incorrect and must by updated manually to be accepted by TRAIAN 3.9. See item 467 in the HISTORY.txt file.


  8. The "sorted set" types was removed from the definition of LOTOS NT. See item 468 in the HISTORY.txt file.

  9. In character and string values, the previous versions of TRAIAN only accepted characters belonging to the octal ranges #040...#176 and #240...#377. The latter range was extended to #200...#377, thus allowing characters in the range #200...#237 as well. See item 472 in the HISTORY.txt file.

  10. The syntax of LOTOS NT was extended to enable process definitions to contain !implementedby "LOTOS:..." and !implementedby "C:..." pragmas. At present, these definitions are syntactically accepted and semantically checked (e.g., to avoid multiple pragmas for a given process, to avoid name clashes between pragmas attached to different processes, etc.), but have no effect. See item 473 in the HISTORY.txt file.

  11. The predefined library of TRAIAN was extended with twelve additional functions:
        =, <> : BOOL, BOOL : BOOL
        =, <> : NAT, NAT : BOOL
        =, <> : INT, INT : BOOL
        =, <> : REAL, REAL : BOOL
        =, <> : CHAR, CHAR : BOOL
        =, <> : STRING, STRING : BOOL
    
    These functions provide alternate notations: "=" is a synonym for "==" and "<>" is a synonym for "!=". See item 474 in the HISTORY.txt file.

  12. The predefined library of LOTOS NT was extended with eight new functions:
       MIN : NAT, NAT -> NAT
       MAX : NAT, NAT -> NAT
       MIN : INT, INT -> INT
       MAX : INT, INT -> INT
       GCD : [ZERO_DIVISION] NAT, NAT -> NAT
       GCD : NAT, NAT -> NAT
       SCM : [ZERO_DIVISION] NAT, NAT -> NAT
       SCM : NAT, NAT -> NAT
    
    This may cause name clashes, e.g., if functions MIN or MAX are already defined with the same profiles in a LOTOS NT program. In such case, the solution is to rename or comment out those functions. See item 475 in the HISTORY.txt file.




Static-Semantics Changes

  1. The data flow analysis performed by TRAIAN was extended to take into account the existence of dead code when emitting the warnings mentioned at items 319, 320, and 321 of the HISTORY.txt file. For instance, the following LOTOS NT program:
       function F [E : none] (X: Bool) : Bool is
          raise E;
          return (not (X))
       end function
    
    now triggers a warning:
       function with result but no normal termination
    
    See item 454 in the HISTORY.txt file.

  2. The way TRAIAN handles field selections "V.F" and field updates "V.{F->...}" was modified. Former versions of TRAIAN would reject such expressions if they could raise an event and no event parameter was given, with error messages such as:
       error: missing exceptional event in field access
       an exception is needed in value:
          V.F
       since V has type T, not all constructors of which have
       a field F
    
    From now, these expressions are accepted at compile-time, but may raise an UNEXPECTED event at run-time, under the assumptions that
       V.F is equivalent to V.[UNEXPECTED] F
    
    and that
       V.{F->...} is equivalent to V.[UNEXPECTED] {F->...}
    
    See item 457 in the HISTORY.txt file.

  3. TRAIAN no longer emits a warning message of the form:
       function with "out" parameter(s) but no normal termination
    
    when the body of a function declared with "out" parameters contains no "return" statement, but raises (e.g., using a "raise" instruction) an event declared in the function profile. Indeed, raising such event can be considered as a normal (or admissible) way of terminating for this function. See item 458 in the HISTORY.txt file.

  4. The static semantics rules for !implementedby pragmas have been enhanced. From now on, the LOTOS names assigned to LOTOS NT functions by means of !implementedby "LOTOS:..." pragmas are no longer required to be unique. This constraint was too strict and did not take into account the fact that LOTOS (contrary to C) allows overloaded function names, and also has separate name spaces for types and functions.

    Therefore, the LOTOS names used in the !implementedby pragmas of LOTOS NT functions may be identical, but they must obey a new rule not to create name clashes. Two LOTOS NT functions may have the same LOTOS name provided that their profiles (argument types and result types) are different. Otherwise, the following error message will be emitted:

       pragma !implementedby "LOTOS:N" already used for same-profile function F at ...
    
    Conversely, the unicity rule remains for C identifiers present in !implementedby "C:..." pragmas, and also for LOTOS type identifiers present in !implementedby "LOTOS:..." pragmas attached to LOTOS NT types. Violations of the latter rule trigger the following error message:
       pragma !implementedby "LOTOS:N" already used for type T at ...
    
    See item 459 in the HISTORY.txt file.

  5. A new constraint was introduced on LOTOS NT functions having both an !implementedby "LOTOS:..." pragma and an !external pragma: such functions must have neither "out" nor "in out" parameters. See item 460 in the HISTORY.txt file.

  6. The data flow analysis was enhanced as follows: from now on, handlers of events that cannot be raised are recognized as dead code and analyzed as such. Consequently, TRAIAN now accepts correct LOTOS NT programs such as :
       function F:int is
          trap
             exception X is null
          in
             return 0
          end trap
        end function
    
    that were previously rejected with the following message:
       error: function F may terminate without returning a value
    
    See item 464 in the HISTORY.txt file.

  7. TRAIAN was made more stringent with respect to non-termination of functions. From now on, the presence, in a function body, of an infinite loop that can be detected statically causes fatal errors instead of warnings:
       error: function with result but looping infinitely
       error: function with "out" parameter but looping infinitely
    
    For instance, the following LOTOS NT programs are rejected with warning and error messages:
       function F (in var X : BOOL) : BOOL is
          while true loop
             X := not (X)
          end loop;
          return X
       end function
    
       function F (in var X : Int) : Int is
          trap
             exception E is
    	    return X
          in
             while true loop
    	    X := X - 1
             end loop;
             raise E
          end trap
       end function
    
    Infinite loops are rejected even if they occur in dead code. For instance, the following LOTOS NT program is rejected:
       function F [E: none] (X: BOOL, out Y: BOOL): BOOL is
          trap
             exception Z is
    	    loop null end loop
          in
             raise E
          end trap;
          return X or Y
       end function
    
    The rationale is that infinite loops in functions are blatantly violating the semantics of LOTOS NT, which assumes that expressions are evaluated atomically and instructions are executed atomically. Even if non-termination cannot be detected in the general case, the increased severity of TRAIAN aims at discouraging users to disseminate infinite loops in their code, even in dead code areas. See item 465 in the HISTORY.txt file.

  8. The static semantics of the "{...}" notation used in patterns and expressions was generalized. Formerly, the type of each "{...}" notation could only be a list type. From now on, this type can be a list, a set, a sorted list, or any type having appropriate NIL and CONS operations. The type of "{...}" depends on the type of its elements and on the context where it occurs. TRAIAN 3.9 implements more involved type checking and emits explanative error messages when no well-typed interpretation of "{...}" can be found. See item 471 in the HISTORY.txt file.

  9. The static semantics of LOTOS NT was modified as follows: from now on, the comparison functions "==" and "!=" are no longer defined by default for each user-defined LOTOS NT type. These functions must now be explicitly defined in a "with" clause, as it is already the case for other functions (e.g., "<", "<=", ">", etc.).

    The former semantics prevented the user from defining specific "==" and "!=" functions for certain types, as previous versions of TRAIAN would report function name clashes in such case.

    Because of this change, many LOTOS NT programs formely accepted may be rejected by TRAIAN 3.9. An easy solution is to add "with ==, !=" in type definitions or, only once, in the module header.

    The C code generated by TRAIAN has been modified to always contain the equality comparison function, even when no "with ==" clause is present in the LOTOS NT code. See item 476 in the HISTORY.txt file.


  10. The static semantics of TRAIAN was extended to accept a larger class of patterns. From now on, TRAIAN no longer requires that patterns only contain constructor functions and free variables. Patterns may also contain non-constructor functions, provided that the arguments of these functions contain neither free variables, nor "as" clauses, nor "any" clauses, nor "where" clauses; but constructors, "of" clauses, and list notations can be used as arguments. The C code generation algorithms of TRAIAN have been extended to handle such generalized patterns. See item 478 in the HISTORY.txt file.




Compiler Changes

  1. The "deprecated" warning messages emitted by TRAIAN have been enhanced to indicate the line number of the first occurrence of a deprecated feature. For instance, the following warning:
       TEST.lnt: "eval" before function calls in instructions is deprecated and should be removed (2 occurrences found)
    
    now displays as follows:
       TEST.lnt:48 "eval" before function calls in instructions is deprecated and should be removed (2 occurrences found)
    
    thus informing the user that the first occurrence appears at line 48. See item 446 in the HISTORY.txt file.

  2. The warning and error messages emitted by TRAIAN have been revised to be displayed in the format used by Gcc and Clang. For instance, the former messages:
       error: TEST.lnt:5: loop L is already defined at TEST.lnt:4
       warning: TEST.lnt:967: useless assignment to DEF
       warning: TEST.lnt:1042: variable Z never used
    
    now display as follows:
       TEST.lnt:5: error: loop L is already defined at TEST.lnt:4
       TEST.lnt:967: warning: useless assignment to DEF
       TEST.lnt:1042: warning: variable Z never used
    
    Also, a few messages have been modified to add missing colons. See item 450 in the HISTORY.txt file.

  3. Some error messages of TRAIAN have been enhanced to display the line number if appropriate, e.g.
       TEST.lnt:313: error: too large natural constant 10000000000000000000000000000
    
    or
       TEST.lnt:16777218: limitation: too many lines (maximum is 16777215)
    
    See item 452 in the HISTORY.txt file.

  4. The format of warning and error messages displayed by TRAIAN was further revised: from now on, all messages that do not contain a file name and a line number are prefixed by "traian:". For instance, the two following messages:
       warning: missing file TEST.tnt for external types
       error: syntax error in ".lnt" file
    
    now display as follows:
       traian: warning: missing file TEST.tnt for external types
       traian: error: "TEST.lnt" is syntactically incorrect
    
    (notice that the latter message was made more informative). See item 453 in the HISTORY.txt file.

  5. The error messages emitted by TRAIAN when a variable or function cannot bind, in a pattern or in an expression, have been enhanced. From now on, TRAIAN no longer emits the message
       error: variable or function F is not defined
    
    if it is certain that F denotes a function, not a variable. The following rules are used: if F is followed with empty parentheses "()", or if the identifier of F is not that of a variable (e.g., 0X0123_456), then F is surely a function and TRAIAN issues the following error message:
       error: function F is not defined
    
    See item 469 in the HISTORY.txt file.

  6. The searching rules of TRAIAN for included modules and libraries have been extended. From now on, TRAIAN searches modules and libraries first in the current directory (as previous versions of TRAIAN did), then in the $LNTDIR/lib directory, and finally in the $CADP/lib directory.

    Also, three libraries borrowed from CADP (BIT.lnt, OCTET.lnt, and OCTETVALUES.lnt) have been added in the "lib" directory of the TRAIAN distribution. See item 470 in the HISTORY.txt file.


  7. TRAIAN was extended to (partially) support arrays, ranges, sorted lists, sets, and predicate types. This was done in a modular way, by introducing a collection of user-readable files located in lib/scheme_*.lnt. From now on, TRAIAN properly does binding and type checking for these various types, imports their constructors (except for arrays), and handles their non-constructor functions that can be imported by means of "with" clauses. Bound checking for range types was implemented.

    At present, C code generation is not yet available for these types (an error message is triggered if a LOTOS NT program contains such types). However, all the aforementioned checks are sufficient for the "-analysis" option of TRAIAN, which can thus be used to check LNT specifications of concurrent systems. See item 479 in the HISTORY.txt file.





Release Changes

  1. A new demo_05 (Hanoi towers) was added to the TRAIAN distribution. See item 445 in the HISTORY.txt file.

  2. The Boehm-Demers garbage collector library was upgraded from version 7.6.4 to version 8.2.2. This made it possible to provide the "win64" version of the garbage collector, which was missing from the TRAIAN 3.8 distribution. See item 449 in the HISTORY.txt file.




Bug Fixes

  1. A bug was fixed in the data flow analysis, which led TRAIAN 3.8 to reject correct LOTOS NT programs such as:
       function F (out X:nat) : BOOL is
          loop L in
             X := 0;
             return true
          end loop
       end function
    
    and:
       function F (out X:nat) : BOOL is
          loop K in
             loop L in
    	    X := 0;
    	    break L
             end loop;
             return false
          end loop;
          return true
       end function
    
    with the following error message:
       function F may return without assigning parameter X
    
    From now on, such programs are accepted by TRAIAN. See item 451 in the HISTORY.txt file.

  2. A bug was fixed in the data flow analysis of TRAIAN 3.8, which caused correct LOTOS NT programs such as the following one:
       function F (out R : Nat) is
          var I : Nat in
             I := 0;
             loop
    	    case I in
    	       any Nat ->
    	          if I == 1 then
    		     R := 1;
    		     return
    	          end if;
    	          I := I + 1
    	    end case
             end loop
          end var
       end function
    
    to be rejected with the error message:
       function F may return without assigning parameter R
    
    From now on, such programs are accepted by TRAIAN. See item 461 in the HISTORY.txt file.

  3. Another bug was fixed in the data flow analysis of TRAIAN 3.8: the events potentially raised in the "by" clauses of "for" loops were not taken into account, thus causing these "for" loops to be improperly considered as infinite loops. For instance, the following LOTOS NT code was rejected:
       function F [E : none] (in var N : NAT) : NAT is
          var R : NAT in
             for R := 1 while true by N := N -[E] 1 loop
    	    if N > 0 then
    	       R := R * N
    	    end if
             end loop;
             return R
          end var
       end function
    
    with an error message:
       function with result but looping infinitely
    
    From now on, this code is accepted by TRAIAN. See item 466 in the HISTORY.txt file.

  4. The following issue was fixed: when a function F was declared simultaneously by the "with" clause of a module M and by the "with" clause of a type T defined in M, TRAIAN issued both a warning:
       redundant clause "with F" for type T (already present for the module)
    
    and a fatal error:
       function F is already defined with the same profile at ...
    
    From now on, only the warning is emitted. See item 477 in the HISTORY.txt file.




Future Work

TRAIAN will continue to evolve, our goal being to merge LOTOS NT and LNT in one single language.


Download

TRAIAN 3.9 can be freely downloaded from the TRAIAN Web Page located at:

http://vasy.inria.fr/traian