Error messages and Warnings Error messages and Warnings

You can cut and paste the code on this page and test it on the online interpreter.

CDuce, statically detects a large class of error and tries to help their debugging by providing precise error messages and, in case of type errors, by showing a description (we call it a "sample") of specific values that would make the computation fail.

CDuce signals the classic syntax errors as well as those for instance of unbound variables. It also checks that pattern matching is exhaustive It checks it in functions, match, and map expressions, but not for transform and xtransform for which a default branch returning the empty sequence is always defined . For instance if we declare the type Person defined in Section "" and try the following definition:

String) | [ n ;_] -> n ]]>

then we obtain the following message error (frames of the same form as the following denote text taken verbatim from the on line demo, no color or formatting added):

String) | [ n ;_] -> n%%}} This pattern matching is not exhaustive Residual type: [ Name Children ] Sample: [ [ ] [ ] ] ]]>

This error message tells us three things: (1) that pattern matching is not defined for all the possible input types (as we forgot the case when the attribute is "M"); (2) it gives us the exact type of the values of the type we have forgotten in our matching (in this case this is exactly MPerson); (3) it shows us a "sample" of the residual type, that is a simplified representation of a value that would make the expression fail (in this case it shows us the value <person gender="M">[ <name>[ ] <children>[ ] ]).

Samples are simplified representations of values in the sense that they show only that part of the value that is relevant for the error and may omit other parts that are needed to obtain an effective value.

CDuce use warnings to signal possible subtler errors. So for instance it issues a warning whenever a capture variable of a pattern is not used in the subsequent expression. This is very useful for instance to detect misprinted types in patterns such as in:

[ x ] ]]>

The intended semantics of this expression was to extract the sequence of all the strings occuring in the matched sequence. But because of the typo in St(r)ing the transformation is instead the identity function: Sting is considered as a fresh capture variable. CDuce however detects that Sting is never used in the subsequent expression and it pinpoints the possible presence of an error by issuing the following warning:

[ x ]%%}} The capture variable Sting is declared in the pattern but not used in the body of this branch. It might be a misspelled or undeclared type or name (if it isn't, use _ instead). %%transform [ 1 "c" 4 "duce" 2 6 ] with x & Sting -> [ x ]%% - : [ 1 [ 'c' ] 4 [ 'duce' ] 2 6 ] = [ 1 "c" 4 "duce" 2 6 ] Ok. ]]>

CDuce's type system can find very nasty errors. For instance look at this DTD declaration

]]>

Apparently this declaration does not pose any problem. But if you consider it more carefully you will see that there exists no document that can be valid for such a DTD, as a person contains a sequence of children that contain a non empty sequence of persons, etc generating an infinite tree.

Let us write the same type in CDuce and look at the result returned by the type-checker

[ Name Children ] type Children = [Person+] type Name = [PCDATA] Warning at chars 57-76: %%type Children = %%{{%%[Person+]%%}} This definition yields an empty type for Children Warning at chars 14-39: %%type Person = %%{{%%[ Name Children ]%%}} This definition yields an empty type for Person ]]>

The type checker correctly issues a "Warning" to signal that the first two types are empty. Note that instead the declarations

[ Name Children ] type Children = [({{ref Person}})+] type Name = [PCDATA] ]]>

correctly do not yield any warning: in this case it is possible to build a value of type person (and thus of type children), for instance by using a recursive definition where a person is a child of itself.

We paid special care in localizing errors and suggesting solutions. You can try it by yourself by picking the examples available on the on line demo and putting in them random errors.

The emptiness test is used also to check for possible errors in the definition of patterns. If the type checker statically determines that a pattern in a match operation can never be matched then it is very likely that even if the match expression is well-typed, the programmer had made an error. This is determined by checking whether the intersection of set of all values that can be fed to the branch and the set of all values that Consider for example the following code:

[String String (String)?] fun main_contacts(x : [Person*]):[String*] = transform x with | <_>[_ _ <{{emal}}>s] -> [s] | <_>[_ s ] -> [s] ]]>

This function was supposed extract the list of contacts from a list of persons elements giving priority to email addresses over telephone numbers. Even if there is a typo in the pattern of the first branch, the function is well typed. However because of the typo the first branch will never be selected and emails never printed. The CDuce type-checker however recognizes that this branch has no chance to be selected since Person & <_>[_ _ <emal>s]=Empty and it warns the programmer by issuing the following warning message:

[_ _ ;s] -> [s]%%}} This branch is not used %%fun main_contacts(x : [Person*]):[String*] = transform x with | <_>[_ _ s] -> [s] | <_>[_ s ] -> [s]%% - : [ Person* ] -> [ String* ] = Ok. ]]>