<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://wiki.visual-prolog.com/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Kehler</id>
	<title>wiki.visual-prolog.com - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://wiki.visual-prolog.com/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Kehler"/>
	<link rel="alternate" type="text/html" href="https://wiki.visual-prolog.com/index.php?title=Special:Contributions/Kehler"/>
	<updated>2026-04-09T20:59:20Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.37.1</generator>
	<entry>
		<id>https://wiki.visual-prolog.com/index.php?title=Collection_library&amp;diff=2377</id>
		<title>Collection library</title>
		<link rel="alternate" type="text/html" href="https://wiki.visual-prolog.com/index.php?title=Collection_library&amp;diff=2377"/>
		<updated>2010-05-26T09:37:22Z</updated>

		<summary type="html">&lt;p&gt;Kehler: /* queue */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;A collection is a value that contains a number (i.e. from zero to infinite) of other values.&lt;br /&gt;
&lt;br /&gt;
Lists, sets, dictionaries, arrays, hash tables, (nondeterm) fact databases, etc are all collections.&lt;br /&gt;
&lt;br /&gt;
A collection can also contain one value, but data types that by nature always contains exactly one value is not a collection.  So a list with one element is a collection, but a variable which also contains one element is not a collection.&lt;br /&gt;
&lt;br /&gt;
[[PFC]] contains an object oriented collection library with both persistent and modifiable collections.  The collection library is based around a set of generic interfaces defining various conceptual collection types, and a number of classes implementing these interfaces.&lt;br /&gt;
&lt;br /&gt;
== Persistent and Modifiable ==&lt;br /&gt;
&lt;br /&gt;
Collections can be persistent or modifiable:&lt;br /&gt;
&lt;br /&gt;
; Persistent&lt;br /&gt;
: A persistent collection never changes members.  Meaning that when you insert or remove a member from persistent collection, you will receive a new collection and the old one will stay unchanged.  Prolog lists is a characteristic example of persistent data types: When you match a list against a pattern to get the head and the tail, the original list stays intact; when you create a list from a new head and an existing list, both the new and the old list will exist.&lt;br /&gt;
&lt;br /&gt;
; Modifiable&lt;br /&gt;
: Members can be added to and removed from a modifiable collection.  Meaning that when you insert or remove a member from a modifiable collection, the old value of the collection is lost only the one exists.  I.e. modifiable collections are updated destructively.  Visual Prolog fact databases is a characteristic example of modifiable data types.  When you assert or retract facts the database is modified and the original fact database is no longer accessible.&lt;br /&gt;
&lt;br /&gt;
== Collection Interfaces &amp;amp; Classes ==&lt;br /&gt;
&lt;br /&gt;
There is no fundamental difference in retrieving data from persistent and modifiable collection.  The difference lies in the updating of the collections.&lt;br /&gt;
&lt;br /&gt;
Therefore retrieval is done through interfaces that are shared by persistent and modifiable collections, whereas updating is done through separate persistent and modifiable interfaces.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;vp&amp;gt;collection&amp;lt;/vp&amp;gt; is most fundamental interface for retrieving inspecting collections all collections supports this interface.  It contains methods:&lt;br /&gt;
* &amp;lt;vp&amp;gt;isEmpty&amp;lt;/vp&amp;gt; determining whether the collection is empty&lt;br /&gt;
* &amp;lt;vp&amp;gt;contains&amp;lt;/vp&amp;gt; testing whether a certain element is in the collection&lt;br /&gt;
* &amp;lt;vp&amp;gt;tryGetFirst&amp;lt;/vp&amp;gt; obtaining the first element in the collection.&lt;br /&gt;
* &amp;lt;vp&amp;gt;getAll_nd&amp;lt;/vp&amp;gt; enumerating all elements in the collection.&lt;br /&gt;
* &amp;lt;vp&amp;gt;asList&amp;lt;/vp&amp;gt; getting the collection in list form.&lt;br /&gt;
&lt;br /&gt;
Notice that &amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039;first&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039; means different things in different kinds of collections.  In a hash table it may for example be the element with the first hash key.&lt;br /&gt;
&lt;br /&gt;
Likewise, the order in which &amp;lt;vp&amp;gt;getAll_nd&amp;lt;/vp&amp;gt; enumerates its elements depends on the collection kind.&lt;br /&gt;
&lt;br /&gt;
Also notice that the performance of some operations may be very poor in some kind of collections. &amp;lt;vp&amp;gt;contains&amp;lt;/vp&amp;gt; is for example a bad operation on a priority queue, because a priority queue not designed to determine membership.&lt;br /&gt;
&lt;br /&gt;
All persistent collections also support the interface &amp;lt;vp&amp;gt;persistent&amp;lt;/vp&amp;gt; and all modifiable collections supports the interface &amp;lt;vp&amp;gt;modifiable&amp;lt;/vp&amp;gt;.  &amp;lt;vp&amp;gt;persistent&amp;lt;/vp&amp;gt; and &amp;lt;vp&amp;gt;modifiable&amp;lt;/vp&amp;gt; have predicates with same names but different types, because the persistent version returns a new collection and the modifiable version doesn&amp;#039;t return anything.  These interfaces have methods:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;vp&amp;gt;insert&amp;lt;/vp&amp;gt;, &amp;lt;vp&amp;gt;insertList&amp;lt;/vp&amp;gt; and &amp;lt;vp&amp;gt;insertCollection&amp;lt;/vp&amp;gt; for inserting elements&lt;br /&gt;
* &amp;lt;vp&amp;gt;remove&amp;lt;/vp&amp;gt;, &amp;lt;vp&amp;gt;removeList&amp;lt;/vp&amp;gt; and &amp;lt;vp&amp;gt;removeCollection&amp;lt;/vp&amp;gt; for removing elements&lt;br /&gt;
* &amp;lt;vp&amp;gt;tryRemoveFirst&amp;lt;/vp&amp;gt; for removing the first element&lt;br /&gt;
* &amp;lt;vp&amp;gt;clear&amp;lt;/vp&amp;gt; for removing all elements in the collection&lt;br /&gt;
&lt;br /&gt;
=== set ===&lt;br /&gt;
&lt;br /&gt;
A &amp;#039;&amp;#039;set&amp;#039;&amp;#039; is a collection of elements, which cannot contain duplicates.  The fundamental set operation is test of membership.  As such a set simply supports the &amp;lt;vp&amp;gt;collection&amp;lt;/vp&amp;gt; interface and one of the interfaces &amp;lt;vp&amp;gt;persistent&amp;lt;/vp&amp;gt; and &amp;lt;vp&amp;gt;modifiable&amp;lt;/vp&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;vp&amp;gt;setP_redBlack&amp;lt;/vp&amp;gt; implements persistent sets based on a red black tree representation.&lt;br /&gt;
* &amp;lt;vp&amp;gt;setM_redBlack&amp;lt;/vp&amp;gt; implements modifiable sets based on a red black tree representation.&lt;br /&gt;
&lt;br /&gt;
=== queue ===&lt;br /&gt;
&lt;br /&gt;
A &amp;#039;&amp;#039;queue&amp;#039;&amp;#039; is a collection of elements which are ordered.  The fundamental operation is getting the first element is the queue.  Membership testing is typically inefficient.  The interfaces of queues is similar to that of sets, supporting &amp;lt;vp&amp;gt;collection&amp;lt;/vp&amp;gt; and one of the interfaces &amp;lt;vp&amp;gt;persistent&amp;lt;/vp&amp;gt; and &amp;lt;vp&amp;gt;modifiable&amp;lt;/vp&amp;gt;.  The names are different to stress the difference in intension and efficeincy.  And in future they may evolve differently.  PFC contains two kinds of queues:&lt;br /&gt;
&lt;br /&gt;
* &amp;#039;&amp;#039;queue&amp;#039;&amp;#039; is a &amp;quot;regular&amp;quot; FIFO (first-in-first-out) queue.&lt;br /&gt;
** &amp;lt;vp&amp;gt;queueP_fact&amp;lt;/vp&amp;gt; implements a persistent FIFO queue based on a fact containing an algebraic queue&lt;br /&gt;
** &amp;lt;vp&amp;gt;queueM_fact&amp;lt;/vp&amp;gt; implements a modifiable FIFO queue based on a nondeterm fact database&lt;br /&gt;
&lt;br /&gt;
* &amp;#039;&amp;#039;priority queue&amp;#039;&amp;#039; is a queue where the first element is alwasy the element with hightst priority (i.e. the least, the greates or based on a custom comparison).&lt;br /&gt;
** &amp;lt;vp&amp;gt;priorityQueueP_leftist&amp;lt;/vp&amp;gt; implements a persistent priority queue&lt;br /&gt;
** &amp;lt;vp&amp;gt;priorityQueueM_leftist&amp;lt;/vp&amp;gt; implements a modifiable priority queue&lt;br /&gt;
Both are based on a leftist tree (see [[wikipedia:Leftist tree]]).&lt;br /&gt;
&lt;br /&gt;
=== map ===&lt;br /&gt;
&lt;br /&gt;
A &amp;#039;&amp;#039;&amp;#039;map&amp;#039;&amp;#039;&amp;#039; is a functionfrom &amp;#039;&amp;#039;keys&amp;#039;&amp;#039; to &amp;#039;&amp;#039;values&amp;#039;&amp;#039;.  Not all keys need have a value.  The basic operations is setting, getting and try-getting the value associated with a certain key.  When the value of a key is set the previous value of that key is &amp;quot;lost&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
A map is a collection of (key,value)-tuples,so the &amp;lt;vp&amp;gt;collection&amp;lt;/vp&amp;gt; predicates all deal with such tuples.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;vp&amp;gt;map&amp;lt;/vp&amp;gt; is the basic interface for inspecting maps (persistent as well as modifiable).  It supports &amp;lt;vp&amp;gt;collection&amp;lt;/vp&amp;gt; of (key,value)-tuples and extends with predicates/properties:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;vp&amp;gt;get&amp;lt;/vp&amp;gt; and &amp;lt;vp&amp;gt;tryGet&amp;lt;/vp&amp;gt; for getting the value associated with a key&lt;br /&gt;
* &amp;lt;vp&amp;gt;getKey_nd&amp;lt;/vp&amp;gt; and &amp;lt;vp&amp;gt;getValue_nd&amp;lt;/vp&amp;gt; for iterating the keys and values&lt;br /&gt;
* &amp;lt;vp&amp;gt;keyList&amp;lt;/vp&amp;gt; and &amp;lt;vp&amp;gt;valueList&amp;lt;/vp&amp;gt; for obtaining all the keys and values as lists.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;vp&amp;gt;mapP&amp;lt;/vp&amp;gt; (persistent maps) and &amp;lt;vp&amp;gt;mapM&amp;lt;/vp&amp;gt; (modifiable maps) supports &amp;lt;vp&amp;gt;map&amp;lt;/vp&amp;gt; and either &amp;lt;vp&amp;gt;persistent&amp;lt;/vp&amp;gt; or &amp;lt;vp&amp;gt;modifiable&amp;lt;/vp&amp;gt;, and extends with:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;vp&amp;gt;set&amp;lt;/vp&amp;gt; for setting the value associated with a key (the previous value associated with that key is &amp;quot;lost&amp;quot;)&lt;br /&gt;
* &amp;lt;vp&amp;gt;removeKey&amp;lt;/vp&amp;gt; for removing a key and its associated value&lt;br /&gt;
* &amp;lt;vp&amp;gt;removeKeyList&amp;lt;/vp&amp;gt; and &amp;lt;vp&amp;gt;removeKeyCollection&amp;lt;/vp&amp;gt; for removing a number of keys and their associated values)&lt;br /&gt;
&lt;br /&gt;
PFC contains persistent and modifiable map classes based on red-black trees:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;vp&amp;gt;mapP_redBlack&amp;lt;/vp&amp;gt;&lt;br /&gt;
* &amp;lt;vp&amp;gt;mapM_redBlack&amp;lt;/vp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Usage examples ==&lt;br /&gt;
&lt;br /&gt;
The examples in this section is inspired by the examples in &amp;#039;&amp;#039;The C5 Generic Collection Library for C# and CLI&amp;#039;&amp;#039;, Niels Kokholm and Peter Sestoft, IT University Technical Report Series TR-2006-76, 2006.&lt;br /&gt;
&lt;br /&gt;
=== Keyword recognition ===&lt;br /&gt;
&lt;br /&gt;
It is often necessary to decide whether a word is member of some fixed collection of words.  For example the keywords of a programming language, or frequent and therefore insignificant (so called stop-words) when indexing text.&lt;br /&gt;
&lt;br /&gt;
Basically, we want to implement a class with a single deterministic predicate that can determine whether a word is a keyword:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;vip&amp;gt;class vipKeyword&lt;br /&gt;
predicates&lt;br /&gt;
    isKeyword : (string Word) determ.&lt;br /&gt;
end class vipKeyword&amp;lt;/vip&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It is a obvious choice to base the implementation on a set of keywords, because member-ship testing is the fundamantal operation of sets. The implementation can look like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;vip&amp;gt;implement vipKeyword&lt;br /&gt;
clauses&lt;br /&gt;
    isKeyword(Word) :-&lt;br /&gt;
        keywordSet:contains(Word).&lt;br /&gt;
&lt;br /&gt;
class facts&lt;br /&gt;
    keywordSet : setM{string Keyword} := initKeywordSet().&lt;br /&gt;
&lt;br /&gt;
class predicates&lt;br /&gt;
    initKeywordSet : () -&amp;gt; setM{string Keyword}.&lt;br /&gt;
clauses&lt;br /&gt;
    initKeywordSet() = S :-&lt;br /&gt;
        S = setM_redBlack::new(),&lt;br /&gt;
        S:insertList(keywords).&lt;br /&gt;
&lt;br /&gt;
constants&lt;br /&gt;
    keywords : string* = [&amp;quot;as&amp;quot;, &amp;quot;class&amp;quot;, &amp;quot;clauses&amp;quot;, ...].&lt;br /&gt;
end implement vipKeyword&amp;lt;/vip&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;vp&amp;gt;isKeyword&amp;lt;/vp&amp;gt; simply determines whether the the &amp;lt;vp&amp;gt;keywordSet&amp;lt;/vp&amp;gt; &amp;lt;vp&amp;gt;contains&amp;lt;/vp&amp;gt; the &amp;lt;vp&amp;gt;Word&amp;lt;/vp&amp;gt; in question.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;vp&amp;gt;keywordSet&amp;lt;/vp&amp;gt; is a (modifiable) set of strings, which is initialized to contain the actual keywords from the &amp;lt;vp&amp;gt;keywords&amp;lt;/vp&amp;gt; constant.&lt;br /&gt;
&lt;br /&gt;
Notice that you should be carefull when initializing class facts like it is done above.  Such initialization is done in an unpredictable order before entering the goal of the program.  So first of all it is difficult to know which other parts of the program that has already been initialized.  Secondly, the exception system is not initialized properly so exceptions will be reported in a rather low-level fasion.&lt;br /&gt;
&lt;br /&gt;
=== Text Concordance ===&lt;br /&gt;
&lt;br /&gt;
A text concordance is a list of words in a text and the lines on which the word occurs, i.e. an index of text.&lt;br /&gt;
&lt;br /&gt;
We will represent that concordance as a map from &amp;lt;vp&amp;gt;Word&amp;lt;/vp&amp;gt; to a set of &amp;lt;vp&amp;gt;Linenumber&amp;lt;/vp&amp;gt;&amp;#039;s, where word is a string and line is an integer.  For convenience we will define a domain:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;vip&amp;gt;domains&lt;br /&gt;
    concordance = mapM{string Word, setM{integer Linenumber}}.&amp;lt;/vip&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To build a concordance from a stream (typically a file), we iterate the lines in the file, and the words of the line.  For each word we insert it in the relevant line number set, which will have to be created if it does not already exist:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;vip&amp;gt;class predicates&lt;br /&gt;
    build : (inputStream Input) -&amp;gt; concordance Concordance.&lt;br /&gt;
clauses&lt;br /&gt;
    build(Input) = Concordance :-&lt;br /&gt;
        Concordance = mapM_redBlack::new(),&lt;br /&gt;
        foreach&lt;br /&gt;
            tuple(Line, Linenumber) = getLine_nd(Input, 1),&lt;br /&gt;
            Word = getWord_nd(Line)&lt;br /&gt;
        do&lt;br /&gt;
            if LinenumberSet = Concordance:tryGet(Word) then&lt;br /&gt;
            else&lt;br /&gt;
                LinenumberSet = setM_redBlack::new(),&lt;br /&gt;
                Concordance:set(Word, LinenumberSet)&lt;br /&gt;
            end if,&lt;br /&gt;
            LinenumberSet:insert(Linenumber)&lt;br /&gt;
        end foreach.&amp;lt;/vip&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Though not important for the main topic the iteration predicates are here:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;vip&amp;gt;class predicates&lt;br /&gt;
    getLine_nd : (inputStream Input, integer NextLine) -&amp;gt; tuple{string Line, integer Linenumber} nondeterm.&lt;br /&gt;
clauses&lt;br /&gt;
    getLine_nd(Input, _NextLine) = _ :-&lt;br /&gt;
        Input:endOfStream(),&lt;br /&gt;
        !,&lt;br /&gt;
        fail.&lt;br /&gt;
&lt;br /&gt;
    getLine_nd(Input, NextLine) = tuple(Line, NextLine) :-&lt;br /&gt;
        Line = Input:readLine().&lt;br /&gt;
&lt;br /&gt;
    getLine_nd(Input, NextLine) = getLine_nd(Input, NextLine+1).&lt;br /&gt;
&lt;br /&gt;
class predicates&lt;br /&gt;
    getWord_nd : (string Line) -&amp;gt; string Word nondeterm.&lt;br /&gt;
clauses&lt;br /&gt;
    getWord_nd(Line) = getWord2_nd(First, Rest) :-&lt;br /&gt;
        string::frontToken(Line, First, Rest).&lt;br /&gt;
&lt;br /&gt;
class predicates&lt;br /&gt;
    getWord2_nd : (string First, string Rest) -&amp;gt; string Word nondeterm.&lt;br /&gt;
clauses&lt;br /&gt;
    getWord2_nd(First, _Rest) = string::toLowerCase(First) :-&lt;br /&gt;
        string::length(First) &amp;gt; 2, % only words with more than 2 letters&lt;br /&gt;
        not(regexp::search(&amp;quot;[^a-zA-Z]&amp;quot;, First, _, _)). % not a word if it contains non-letters&lt;br /&gt;
&lt;br /&gt;
    getWord2_nd(_First, Rest) = getWord_nd(Rest).&amp;lt;/vip&amp;gt;&lt;br /&gt;
&lt;br /&gt;
From a concordance we can print an index, by iterating the &amp;lt;vp&amp;gt;(Word, LinenumberSet)&amp;lt;/vp&amp;gt; tuples in the &amp;lt;vp&amp;gt;Concordance&amp;lt;/vp&amp;gt;, and the &amp;lt;vp&amp;gt;Linenumber&amp;lt;/vp&amp;gt;&amp;#039;s in the &amp;lt;vp&amp;gt;LinenumberSet&amp;lt;/vp&amp;gt;&amp;#039;s.  Since both the maps and the sets are based on red-black trees everything is automatically sorted for us:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;vip&amp;gt;class predicates&lt;br /&gt;
    print : (outputStream Output, concordance Concordance).&lt;br /&gt;
clauses&lt;br /&gt;
    print(Output, Concordance) :-&lt;br /&gt;
        foreach tuple(Word, LinenumberSet) = Concordance:getAll_nd() do&lt;br /&gt;
            Output:writef(&amp;quot;%:\n&amp;quot;, Word),&lt;br /&gt;
            foreach Linenumber = LinenumberSet:getAll_nd() do&lt;br /&gt;
                Output:writef(&amp;quot;   %\n&amp;quot;, Linenumber)&lt;br /&gt;
            end foreach,&lt;br /&gt;
            Output:write(&amp;quot;\n&amp;quot;)&lt;br /&gt;
        end foreach.&amp;lt;/vip&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== References ==&lt;br /&gt;
&lt;br /&gt;
* [http://www.itu.dk/research/c5/ The C5 Generic Collection Library for C# and CLI]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:PFC]]&lt;br /&gt;
[[Category:Tutorials]]&lt;/div&gt;</summary>
		<author><name>Kehler</name></author>
	</entry>
	<entry>
		<id>https://wiki.visual-prolog.com/index.php?title=Exception_Handling&amp;diff=2115</id>
		<title>Exception Handling</title>
		<link rel="alternate" type="text/html" href="https://wiki.visual-prolog.com/index.php?title=Exception_Handling&amp;diff=2115"/>
		<updated>2010-01-23T11:51:00Z</updated>

		<summary type="html">&lt;p&gt;Kehler: /* Defining an exception */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;An exception is a deviation from the expected.  What is an exception in one context may be expected in another context, and thus not an exception in that context.&lt;br /&gt;
&lt;br /&gt;
In Visual Prolog programs exceptions are used to deal with deviations from what is expected in the given context.  When a certain program part gets into a situation it cannot deal with it can &amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039;raise&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039; an exception.  When an exception is raised the program control is transferred to the nearest &amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039;exception handler&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039;.  If the exception handler cannot handle the exception it can either raise a new exception or &amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039;continue&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039; the original exception.&lt;br /&gt;
&lt;br /&gt;
The program will terminate with an error message if there is no exception handler to transfer the control to.&lt;br /&gt;
&lt;br /&gt;
== Introduction to exception handling  ==&lt;br /&gt;
&lt;br /&gt;
There are many concepts and entities to understand when dealing with exceptions.  This section will give an introduction by means of an example.&lt;br /&gt;
&lt;br /&gt;
A certain program needs to write some information to a file.  Therefore it has a predicate &amp;lt;vp&amp;gt;writeInfo&amp;lt;/vp&amp;gt; that can write this information.  &amp;lt;vp&amp;gt;writeInfo&amp;lt;/vp&amp;gt; calls the PFC constructor &amp;lt;vp&amp;gt;outputStream_file::create&amp;lt;/vp&amp;gt; to obtain a stream that it can write the information to:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;vip&amp;gt;clauses&lt;br /&gt;
    writeInfo(Filename) :-&lt;br /&gt;
        S = outputStream_file::create(Filename),&lt;br /&gt;
        …&amp;lt;/vip&amp;gt;&lt;br /&gt;
&lt;br /&gt;
But if the file already exists and is write-protected it is impossible to create the stream.&lt;br /&gt;
&lt;br /&gt;
In &amp;lt;vp&amp;gt;outputStream_file::create&amp;lt;/vp&amp;gt; this situation is considered to be exceptional/unexpected and therefore it raises an exception.&lt;br /&gt;
&lt;br /&gt;
When an exception is raised the program control is transferred to the nearest exception handler, which can hopefully handle the situation and thus bring the program back on track again.&lt;br /&gt;
&lt;br /&gt;
In this case &amp;lt;vp&amp;gt;writeInfo&amp;lt;/vp&amp;gt; is called after the user have entered the file name in a dialog and pressed a &amp;#039;&amp;#039;&amp;#039;Save&amp;#039;&amp;#039;&amp;#039;-button.  So the handling we want is simply to tell the user that the information was not written because the file was write-protected.  The user can choose a different filename, remove the write protection, delete the file, cancel the operation entirely or something else.  But from the program&amp;#039;s point of view the exceptional situation is handled.&lt;br /&gt;
&lt;br /&gt;
To set a handler we use the {{lang2|Terms|try-catch|try-catch}} language construction:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;vip&amp;gt;clauses&lt;br /&gt;
    saveInfo(Filename) :-&lt;br /&gt;
        try&lt;br /&gt;
            writeInfo(Filename)&lt;br /&gt;
         catch TraceId do&lt;br /&gt;
              % &amp;lt;&amp;lt;handle situation&amp;gt;&amp;gt;&lt;br /&gt;
         end try.&amp;lt;/vip&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The code works like this:  &amp;lt;vp&amp;gt;writeInfo&amp;lt;/vp&amp;gt; is called, if it succeeds the {{lang2|Terms|try-catch|try-catch}} construction will not do more and &amp;lt;vp&amp;gt;saveInfo&amp;lt;/vp&amp;gt; will also succeed.&lt;br /&gt;
&lt;br /&gt;
But in the write-protected case &amp;lt;vp&amp;gt;outputStream_file::create&amp;lt;/vp&amp;gt; will raise an exception and therefore the following will take place:&lt;br /&gt;
&lt;br /&gt;
# &amp;lt;vp&amp;gt;TraceId&amp;lt;/vp&amp;gt; will be bound to the (so called) &amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039;trace id&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039;, which is a handle to information about the exception (described in more details below)&lt;br /&gt;
# The handler code (i.e. the code between &amp;lt;vp&amp;gt;do&amp;lt;/vp&amp;gt; and &amp;lt;vp&amp;gt;end try&amp;lt;/vp&amp;gt;) is evaluated&lt;br /&gt;
# The result of the handler code will be the result of the {{lang2|Terms|try-catch|try-catch}} construction, and thus of &amp;lt;vp&amp;gt;saveInfo&amp;lt;/vp&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
So for the &amp;quot;write-protected&amp;quot; exception the handler code should write a message to the user.&lt;br /&gt;
&lt;br /&gt;
If it is another kind of exception the handler will have to do something different.  Especially, it may be an exception that the handler does not know how to handle.  In this case the best thing the handler code can do is to continue the exception as an &amp;#039;&amp;#039;unknown&amp;#039;&amp;#039; exception (i.e. unknown to the handler).&lt;br /&gt;
&lt;br /&gt;
When an exception is continued it consists of the original exception plus some continue information.  If it has been continued by several handlers it will contain a lot of continue information in addition to the original exception information.  The exception information describes a trace from the point of raise through all the handlers.  The &amp;lt;vp&amp;gt;TraceId&amp;lt;/vp&amp;gt; variable that is bound in the {{lang2|Terms|try-catch|try-catch}} construction gives access information about the entire trace (hence the name).&lt;br /&gt;
&lt;br /&gt;
As mentioned above the program will terminate with en error message, if an exception is raised and no handler can be found.  Therefore programs normally setup an outermost default exception handler.  &amp;lt;vp&amp;gt;mainExe::run&amp;lt;/vp&amp;gt; setup such a handler in a console program this is the fall-back handler.  In a GUI program there is also a default hander in the GUI event loop which will catch exceptions arising from the handling of an event.&lt;br /&gt;
&lt;br /&gt;
All in all, the lifecycle of an exception is as follows:&lt;br /&gt;
&lt;br /&gt;
* It is raised&lt;br /&gt;
* It is caught and continued&lt;br /&gt;
* It is caught and continued&lt;br /&gt;
* …&lt;br /&gt;
* It is caught and handled (or the program terminates with an error message)&lt;br /&gt;
&lt;br /&gt;
Each time the exception is caught the trace so far can be examined.  When the exception is raised and each time it is continued extra information can be added to the exception trace.  If nothing else handles an exception it will (normally) be handled by the fallback/default handler of the program.&lt;br /&gt;
&lt;br /&gt;
== Defining an exception ==&lt;br /&gt;
&lt;br /&gt;
An exception is a value of the type &amp;lt;vp&amp;gt;core::exception&amp;lt;/vp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;vip&amp;gt;domains&lt;br /&gt;
    exception = (classInfo ClassInfo [out], string PredicateName [out], string Description [out]).&amp;lt;/vip&amp;gt;&lt;br /&gt;
&lt;br /&gt;
I.e. an exception is a predicate that returns three pieces of information:&lt;br /&gt;
&lt;br /&gt;
; &amp;lt;vp&amp;gt;ClassInfo&amp;lt;/vp&amp;gt;&lt;br /&gt;
: The &amp;lt;vp&amp;gt;classInfo&amp;lt;/vp&amp;gt; of the class that defines the exception&lt;br /&gt;
; &amp;lt;vp&amp;gt;PredicateName&amp;lt;/vp&amp;gt;&lt;br /&gt;
: The name of the exception predicate itself&lt;br /&gt;
; &amp;lt;vp&amp;gt;Description&amp;lt;/vp&amp;gt;&lt;br /&gt;
: A description of the exception&lt;br /&gt;
&lt;br /&gt;
{{example| The &amp;lt;vp&amp;gt;cannotCreate&amp;lt;/vp&amp;gt; exception from the example above is declared in the class &amp;lt;vp&amp;gt;fileSystem_api&amp;lt;/vp&amp;gt; like this:&lt;br /&gt;
&amp;lt;vip&amp;gt;class fileSystem_api&lt;br /&gt;
…&lt;br /&gt;
predicates&lt;br /&gt;
    cannotCreate : exception.&lt;br /&gt;
…&amp;lt;/vip&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The implementation looks like this:&lt;br /&gt;
&amp;lt;vip&amp;gt;implement fileSystem_api&lt;br /&gt;
…&lt;br /&gt;
clauses&lt;br /&gt;
    cannotCreate(classInfo, predicate_name(), &amp;quot;Cannot create or open the specified file&amp;quot;).&lt;br /&gt;
…&amp;lt;/vip&amp;gt;&lt;br /&gt;
&amp;lt;vp&amp;gt;classInfo&amp;lt;/vp&amp;gt; is the &amp;lt;vp&amp;gt;classInfo&amp;lt;/vp&amp;gt; of the &amp;lt;vp&amp;gt;fileSystem_api&amp;lt;/vp&amp;gt; class ; &amp;lt;vp&amp;gt;predicate_name&amp;lt;/vp&amp;gt; is a built-in predicate  that returns the name of the predicate in which it is called (i.e. in this case it will return &amp;lt;vp&amp;gt;&amp;quot;cannotCreate&amp;quot;&amp;lt;/vp&amp;gt;).  The last argument is the description of the exception. &lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Many/most programmers will never need to define exceptions, because in many/most cases the exceptions to use are already defined.  An exception definition is only needed when the exception must be distinguished from other kinds of exceptions, such that exception handlers can deal specially with that kind of exception.  Typically exception definitions are only necessary for exceptions that are raised by library software.  I most cases programmers will raise the exception &amp;lt;vp&amp;gt;internal_error&amp;lt;/vp&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Raising an exception ==&lt;br /&gt;
&lt;br /&gt;
Exceptions are raised using the predicate &amp;lt;vp&amp;gt;exception::raise&amp;lt;/vp&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;vip&amp;gt;class exception&lt;br /&gt;
…&lt;br /&gt;
predicates&lt;br /&gt;
    raise : (classInfo ClassInfo, exception Exception) erroneous. &lt;br /&gt;
    raise : (classInfo ClassInfo, exception Exception, namedValue_list ExtraInfo) erroneous.&amp;lt;/vip&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;vp&amp;gt;ClassInfo&amp;lt;/vp&amp;gt;&lt;br /&gt;
: The &amp;lt;vp&amp;gt;classInfo&amp;lt;/vp&amp;gt; of the class that raise the excption&lt;br /&gt;
&amp;lt;vp&amp;gt;Exception&amp;lt;/vp&amp;gt;&lt;br /&gt;
: The exception to raise&lt;br /&gt;
&amp;lt;vp&amp;gt;ExtraInfo&amp;lt;/vp&amp;gt;&lt;br /&gt;
: Extra information about the raised exception.&lt;br /&gt;
&lt;br /&gt;
{{example|The &amp;lt;vp&amp;gt;cannotCreate&amp;lt;/vp&amp;gt; exception from above is raised by the predicate &amp;lt;vp&amp;gt;fileSystem_api::raise_cannotCreate&amp;lt;/vp&amp;gt;. The code  looks like this:&lt;br /&gt;
&amp;lt;vip&amp;gt;clauses&lt;br /&gt;
    raise_cannotCreate(ClassInfo, FileName, LastError) :-&lt;br /&gt;
        Desc = common_exception::getLastErrorDescription(LastError),&lt;br /&gt;
        exception::raise(&lt;br /&gt;
            ClassInfo,&lt;br /&gt;
            cannotCreate,&lt;br /&gt;
            [namedValue(fileSystem_exception::fileName_parameter, string(FileName)),&lt;br /&gt;
             namedValue(common_exception::errorCode_parameter, unsigned(LastError)),&lt;br /&gt;
             namedValue(common_exception::errorDescription_parameter, string(Desc))]).&amp;lt;/vip&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;vp&amp;gt;raise_cannotCreate&amp;lt;/vp&amp;gt; is called with the &amp;lt;vp&amp;gt;ClassInfo&amp;lt;/vp&amp;gt; of the raising class the &amp;lt;vp&amp;gt;FileName&amp;lt;/vp&amp;gt; and the windows error code &amp;lt;vp&amp;gt;LastError&amp;lt;/vp&amp;gt; that the relevant low level Windows API predicate caused.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;vp&amp;gt;common_exception::getLastErrorDescription&amp;lt;/vp&amp;gt; obtains the description corresponding to &amp;lt;vp&amp;gt;LastError&amp;lt;/vp&amp;gt; from Windows.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;vp&amp;gt;exception::raise&amp;lt;/vp&amp;gt; is then used to raise the &amp;lt;vp&amp;gt;cannotCreate&amp;lt;/vp&amp;gt; exception with the three pieces of extra information.   &amp;lt;vp&amp;gt;fileSystem_exception::fileName_parameter&amp;lt;/vp&amp;gt;, &amp;lt;vp&amp;gt;common_exception::errorCode_parameter&amp;lt;/vp&amp;gt; and &amp;lt;vp&amp;gt;common_exception::errorDescription_parameter&amp;lt;/vp&amp;gt; are names (strings) used for the extra information. &lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
It is very common to create helper predicates like  &amp;lt;vp&amp;gt;fileSystem_api::raise_cannotCreate&amp;lt;/vp&amp;gt; to do the actual raising rather that calling &amp;lt;vp&amp;gt;exception::raise&amp;lt;/vp&amp;gt; directly from the code that needs to raise the exception.  That way it is certain that the extra info for this particular exception is handled in the same way in all cases.&lt;br /&gt;
&lt;br /&gt;
Normally the helper raise predicate is created by the same programmer that declares the exception.  And as mentioned above this is normally only programmers that create library software.&lt;br /&gt;
&lt;br /&gt;
Application programmers will in most cases raise exceptions by calling appropriate raiser predicates, typically the ones defined in &amp;lt;vp&amp;gt;common_exception&amp;lt;/vp&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Catching and handling exceptions ==&lt;br /&gt;
&lt;br /&gt;
Exceptions are caught with the {{lang2|Terms|try-catch|try-catch}} construction:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;vipbnf&amp;gt;try &amp;lt;Body&amp;gt; catch &amp;lt;TraceId&amp;gt; do &amp;lt;Handler&amp;gt; end try&amp;lt;/vipbnf&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If &amp;lt;vpbnf&amp;gt;&amp;lt;Body&amp;gt;&amp;lt;/vpbnf&amp;gt; terminates with an exception &amp;lt;vpbnf&amp;gt;&amp;lt;TraceId&amp;gt;&amp;lt;/vpbnf&amp;gt; is bound to the &amp;#039;&amp;#039;trace id&amp;#039;&amp;#039; and then &amp;lt;vpbnf&amp;gt;&amp;lt;Handler&amp;gt;&amp;lt;/vpbnf&amp;gt; is evaluated.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;vpbnf&amp;gt;&amp;lt;TraceId&amp;gt;&amp;lt;/vpbnf&amp;gt; is used to obtain information about the exception trace.  This information can be used for at least two things:&lt;br /&gt;
&lt;br /&gt;
* Determine which kind of exception that is caught, so that it can be decided if and how to handle it&lt;br /&gt;
* Obtain additional information to write to the user, in a log or use for something else&lt;br /&gt;
&lt;br /&gt;
You will call &amp;lt;vp&amp;gt;exception::tryGetDescriptor&amp;lt;/vp&amp;gt; to determine if a certain kind of exception is caught:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;vip&amp;gt;predicates&lt;br /&gt;
    tryGetDescriptor : (traceId TraceID, exception Exception) -&amp;gt; descriptor Descriptor determ.&amp;lt;/vip&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The exception trace corresponding to &amp;lt;vp&amp;gt;TraceId&amp;lt;/vp&amp;gt; is searched for an exception of the kind &amp;lt;vp&amp;gt;Exception&amp;lt;/vp&amp;gt;.  If there is such an entry in the trace (raised or continued) a corresponding exception descriptor is returned in &amp;lt;vp&amp;gt;Descriptor&amp;lt;/vp&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The predicate fails if such an exception is not in the exception trace.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;vp&amp;gt;Descriptor&amp;lt;/vp&amp;gt; contains the extra information about that particular entry in the exception trace:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;vip&amp;gt;domains&lt;br /&gt;
    descriptor = descriptor(classInfoDescriptor ClassInfo, exceptionDescriptor ExceptionInfo, kind Kind,&lt;br /&gt;
        namedValue_list ExtraInfo, gmtTimeValue GMTTime, string ExceptionDescription, unsigned ThreadId).&amp;lt;/vip&amp;gt;&lt;br /&gt;
&lt;br /&gt;
; &amp;lt;vp&amp;gt;ClassInfo&amp;lt;/vp&amp;gt;&lt;br /&gt;
: The &amp;lt;vp&amp;gt;classInfo&amp;lt;/vp&amp;gt; of the class that raised the exception (in functor form)&lt;br /&gt;
; &amp;lt;vp&amp;gt;ExceptionInfo&amp;lt;/vp&amp;gt;&lt;br /&gt;
: The &amp;lt;vp&amp;gt;exception&amp;lt;/vp&amp;gt; in question (in functor form)&lt;br /&gt;
; &amp;lt;vp&amp;gt;Kind&amp;lt;/vp&amp;gt;&lt;br /&gt;
: The entry kind (&amp;lt;vp&amp;gt;raise&amp;lt;/vp&amp;gt; or &amp;lt;vp&amp;gt;continue&amp;lt;/vp&amp;gt;)&lt;br /&gt;
; &amp;lt;vp&amp;gt;ExtraInfo&amp;lt;/vp&amp;gt;&lt;br /&gt;
: The extra information provided with this entry in the trace&lt;br /&gt;
; &amp;lt;vp&amp;gt;GMTTime&amp;lt;/vp&amp;gt;&lt;br /&gt;
: The time this exception trace entry was raised/continued&lt;br /&gt;
; &amp;lt;vp&amp;gt;ExceptionDescription&amp;lt;/vp&amp;gt;&lt;br /&gt;
: The exception description of this entry (this information is also present in &amp;lt;vp&amp;gt;ExceptionInfo&amp;lt;/vp&amp;gt;)&lt;br /&gt;
; &amp;lt;vp&amp;gt;ThreadId&amp;lt;/vp&amp;gt;&lt;br /&gt;
: The thread id of the thread that raised/continued this entry&lt;br /&gt;
&lt;br /&gt;
Much of this information is mainly interesting if the exception is not handled.  The information that is most interesting when handling an exception is:&lt;br /&gt;
&lt;br /&gt;
* The exception kind has been determined to be the one we expected&lt;br /&gt;
* The &amp;lt;vp&amp;gt;ExtraInfo&amp;lt;/vp&amp;gt; for this entry is available for use in messages, etc&lt;br /&gt;
&lt;br /&gt;
The predicate &amp;lt;vp&amp;gt;exception::tryGetExtraInfo&amp;lt;/vp&amp;gt; is convenient for obtaining extra information:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;vip&amp;gt;predicates&lt;br /&gt;
    tryGetExtraInfo : (descriptor Descriptor, string Name) -&amp;gt; value Value determ.&amp;lt;/vip&amp;gt;&lt;br /&gt;
&lt;br /&gt;
; &amp;lt;vp&amp;gt;Descriptor&amp;lt;/vp&amp;gt;&lt;br /&gt;
: Is the description whose extra info we want to get something from.&lt;br /&gt;
; &amp;lt;vp&amp;gt;Name&amp;lt;/vp&amp;gt;&lt;br /&gt;
: The name of the extra info parameter we want to obtain.&lt;br /&gt;
; &amp;lt;vp&amp;gt;Value&amp;lt;/vp&amp;gt;&lt;br /&gt;
: The value that the mentioned parameter has.&lt;br /&gt;
&lt;br /&gt;
{{example|  Code for catching and handling the &amp;lt;vp&amp;gt;fileSystem_api::cannotCreate&amp;lt;/vp&amp;gt; exception can look like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;vip&amp;gt;clauses&lt;br /&gt;
    saveInfo(Filename) :-&lt;br /&gt;
        try&lt;br /&gt;
            writeInfo(Filename)&lt;br /&gt;
         catch TraceId do&lt;br /&gt;
              if D = exception::tryGetDescriptor(TraceId, fileSystem_api::cannotCreate) then&lt;br /&gt;
                stdio::write(&amp;quot;Cannot write to the file: &amp;quot;, Filename),&lt;br /&gt;
                if string(Description) = exception::tryGetExtraInfo(D, common_exception::errorDescription_parameter) then&lt;br /&gt;
                    stdio::writef(&amp;quot;; %&amp;quot;, Description)&lt;br /&gt;
                end if,&lt;br /&gt;
                stdio::write(&amp;quot;\n&amp;quot;)&lt;br /&gt;
            else&lt;br /&gt;
                common_exception::continue_unknown(TraceId, classInfo, predicate_name(), &amp;quot;Filename = &amp;quot;, Filename)&lt;br /&gt;
            end if&lt;br /&gt;
         end try.&amp;lt;/vip&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The code here don&amp;#039;t need to obtain the &amp;lt;vp&amp;gt;fileSystem_exception::fileName_parameter&amp;lt;/vp&amp;gt;, because the file name is already known in the &amp;lt;vp&amp;gt;Filename&amp;lt;/vp&amp;gt; variable.&lt;br /&gt;
&lt;br /&gt;
But we can obtain Window&amp;#039;s description of the problem querying for &amp;lt;vp&amp;gt;common_exception::errorDescription_parameter&amp;lt;/vp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We &amp;#039;&amp;#039;&amp;#039;continue&amp;#039;&amp;#039;&amp;#039; the exception as unknown if it is not the &amp;lt;vp&amp;gt;cannotCreate&amp;lt;/vp&amp;gt; kind .  For the continue call we add the filename as.  &amp;lt;vp&amp;gt;common_exception::continue_unknown&amp;lt;/vp&amp;gt; will create a string of the extra arguments and add it as an &amp;lt;vp&amp;gt;common_exception::errorArguments_parameter&amp;lt;/vp&amp;gt;.  Such information is mainly for use in the default exception handler to be discussed below. &lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== Serializing exceptions ==&lt;br /&gt;
&lt;br /&gt;
In some situations the best way to handle  an exception is by sending all the information about the exception somewhere else.  A server might for example want to send the information to the client program that caused the exception, because then there is a user that can take action.&lt;br /&gt;
&lt;br /&gt;
A &amp;lt;vp&amp;gt;traceId&amp;lt;/vp&amp;gt; only have a meaning in the process that has created it, but the predicate &amp;lt;vp&amp;gt;exception::getTraceInfo&amp;lt;/vp&amp;gt; can create a &amp;lt;vp&amp;gt;traceInfo&amp;lt;/vp&amp;gt; structure (&amp;lt;vp&amp;gt;TraceInfo&amp;lt;/vp&amp;gt;) from the &amp;lt;vp&amp;gt;traceId TraceId&amp;lt;/vp&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;vip&amp;gt;predicates&lt;br /&gt;
    getTraceInfo : (traceId TraceId) -&amp;gt; traceInfo TraceInfo.&amp;lt;/vip&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Such a structure is a functor structure that can be serialized/deserialized with &amp;lt;vp&amp;gt;toString&amp;lt;/vp&amp;gt;/&amp;lt;vp&amp;gt;toTerm&amp;lt;/vp&amp;gt;; &amp;lt;vp&amp;gt;write&amp;lt;/vp&amp;gt;/&amp;lt;vp&amp;gt;read&amp;lt;/vp&amp;gt;; nested in a fact database using &amp;lt;vp&amp;gt;save&amp;lt;/vp&amp;gt;/&amp;lt;vp&amp;gt;consult&amp;lt;/vp&amp;gt;; etc.&lt;br /&gt;
&lt;br /&gt;
== Exception dumps ==&lt;br /&gt;
&lt;br /&gt;
The class &amp;lt;vp&amp;gt;exceptionDump&amp;lt;/vp&amp;gt; contains predicates for dumping exception traces to &amp;lt;vp&amp;gt;stdio&amp;lt;/vp&amp;gt;, some other &amp;lt;vp&amp;gt;outputStream&amp;lt;/vp&amp;gt; or a &amp;lt;vp&amp;gt;string&amp;lt;/vp&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
An exception dump contains three major pieces of information:&lt;br /&gt;
&lt;br /&gt;
* A dump of the call stack (with file names and line numbers) from the point where the exception was raised&lt;br /&gt;
* A dump of the exception-trace with all the information from the exception descriptors&lt;br /&gt;
* Information about the operating system that the program ran on&lt;br /&gt;
 &lt;br /&gt;
&amp;lt;vp&amp;gt;exceptionDump&amp;lt;/vp&amp;gt; have predicates both for dumping exception traces both from a &amp;lt;vp&amp;gt;traceId&amp;lt;/vp&amp;gt; and from a &amp;lt;vp&amp;gt;traceInfo&amp;lt;/vp&amp;gt; obtained with &amp;lt;vp&amp;gt;exception::getTraceInfo&amp;lt;/vp&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Dumps for a certain program are in general only useful to the programmers of that program; the users of the program will find dumps cryptic and rather uninteresting.  I.e. the purpose of dumps is to give the programmer means for improving the program.&lt;br /&gt;
&lt;br /&gt;
== Default handling ==&lt;br /&gt;
&lt;br /&gt;
A program should handle all exceptions, because if an exception is continued or raised at a point where there is no handler the program will terminate with a rather bad error message.  The error message is bad because most exception handling is done in PFC; the language itself knows nothing about exception traces and the like.&lt;br /&gt;
&lt;br /&gt;
To be sure that all exceptions are handled it is normal to set up a default (or fallback) exception handler.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;vp&amp;gt;mainExe::run&amp;lt;/vp&amp;gt; (and &amp;lt;vp&amp;gt;mainExe::runCom&amp;lt;/vp&amp;gt;) which is normally called in the goal setup such a default exception handler: It runs the &amp;lt;vp&amp;gt;main::run&amp;lt;/vp&amp;gt; predicate inside a {{lang2|Terms|try-catch|try-catch}} construction that will handle any exception.&lt;br /&gt;
&lt;br /&gt;
The handler in &amp;lt;vp&amp;gt;mainExe::run&amp;lt;/vp&amp;gt; (and &amp;lt;vp&amp;gt;mainExe::runCom&amp;lt;/vp&amp;gt;) dumps the entire exception trace to output stream in &amp;lt;vp&amp;gt;stdio&amp;lt;/vp&amp;gt;.  And then the program will terminate.  The idea is that:&lt;br /&gt;
&lt;br /&gt;
* Perhaps the user can see something from the dump (which may for example say that &amp;#039;&amp;#039;access is denied&amp;#039;&amp;#039; to &amp;#039;&amp;#039;xxx.txt&amp;#039;&amp;#039;)&lt;br /&gt;
* Alternatively, the developer of the program may use the dump to improve the program&lt;br /&gt;
&lt;br /&gt;
In addition to the handler in &amp;lt;vp&amp;gt;mainExe::run&amp;lt;/vp&amp;gt; a GUI program also set a default handler in the event loop.  This handler is set by calling &amp;lt;vp&amp;gt;applicationWindow::setErrorResponder&amp;lt;/vp&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;vip&amp;gt;domains&lt;br /&gt;
    errorResponder = (applicationWindow Source, exception::traceId TraceId).&lt;br /&gt;
&lt;br /&gt;
predicates&lt;br /&gt;
    setErrorResponder : (errorResponder Responder).&amp;lt;/vip&amp;gt;&lt;br /&gt;
&lt;br /&gt;
By default the error responder &amp;lt;vp&amp;gt;errorPresentationDialog::present&amp;lt;/vp&amp;gt; is used.  The functioning of the &amp;lt;pv&amp;gt;errorPresentationDialog&amp;lt;/vp&amp;gt; is closely related to a categorization of exceptions described in the next section.&lt;br /&gt;
&lt;br /&gt;
PFC place exceptions in three major categories based on who is (believed to be) responsible:&lt;br /&gt;
&lt;br /&gt;
; Internal errors&lt;br /&gt;
: An exceptional state which the programmer is responsible to deal with&lt;br /&gt;
; User exceptions&lt;br /&gt;
: An exception which can perhaps be solved by the end user of the program, but which may also call for a programmer solution.  User exceptions carries a message for the end user of the program.&lt;br /&gt;
; Definite user errors&lt;br /&gt;
: An exception which is definitely one the end user should deal with, because the programmer cannot do anything about it anyway&lt;br /&gt;
&lt;br /&gt;
You may notice that &amp;quot;error&amp;quot; is used to signal that a person is (believed to be) responsible for the problem, where as &amp;quot;exception&amp;quot; also covers situations with looser relation to specific persons (such as a network failure).&lt;br /&gt;
&lt;br /&gt;
=== Internal errors ===&lt;br /&gt;
&lt;br /&gt;
Internal errors are caused and/or should be prevented by the programmer of the program.&lt;br /&gt;
&lt;br /&gt;
{{Example| A predicate takes two lists as argument and pair the elements of the lists.  So the lists are expected to have the same length.  If the lists have different lengths it is appropriate to raise an &amp;lt;vp&amp;gt;internal_error&amp;lt;/vp&amp;gt;, because it is clearly the responsibility of the programmer to ensure that the lists have same length; the end-user of the program can at most influence this indirectly.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== User exceptions ===&lt;br /&gt;
&lt;br /&gt;
User exceptions typically deal with problems related to external resources such as files, network, databases, web servers, etc.  Often the user will become wiser by being informed about the problem and often the user may even solve the problem.&lt;br /&gt;
&lt;br /&gt;
{{Example|  The read-only file problem discussed above is a typical example of a user exception.  It is the user rather than the programmer that can solve the problem with the read-only file.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
A user exception is distinguished by having extra information in a field with name &amp;lt;vp&amp;gt;common_exception::userMessage_parameter&amp;lt;/vp&amp;gt;.  This extra info should be a message with relevance for an end user of the program.  The message can reference other extra info parameters using the format %PARAM.  The preferred way to raise user exceptions is by means of the predicate &amp;lt;vp&amp;gt;common_exception::raise_user&amp;lt;/vp&amp;gt;.  Likewise you can continue exceptions with a user message using &amp;lt;vp&amp;gt;common_exception::continue_user&amp;lt;/vp&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
{{Example| This predicate will raise a &amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039;user&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039; &amp;lt;vp&amp;gt;fileSystem_api::cannotCreate&amp;lt;/vp&amp;gt; exception &lt;br /&gt;
&lt;br /&gt;
&amp;lt;vip&amp;gt;class predicates&lt;br /&gt;
    raise_cannotCreate : (string Filename) erroneous.&lt;br /&gt;
clauses&lt;br /&gt;
    raise_cannotCreate(Filename) :-&lt;br /&gt;
        common_exception::raise_user(classInfo, fileSystem_api::cannotCreate, predicate_name(),&lt;br /&gt;
            &amp;quot;It is not possible to create the file %Filename&amp;quot;,&lt;br /&gt;
            [namedValue(&amp;quot;Filename&amp;quot;, string(Filename))]).&amp;lt;/vip&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The use of &amp;lt;vp&amp;gt;&amp;quot;%Filename&amp;quot;&amp;lt;/vp&amp;gt; in the message corresponds to the extra info &amp;lt;vp&amp;gt;&amp;quot;Filename&amp;quot;&amp;lt;/vp&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
The predicate &amp;lt;vp&amp;gt;exceptionDump::tryGetUserMessage&amp;lt;/vp&amp;gt; will return a user message from a &amp;lt;vp&amp;gt;traceId&amp;lt;/vp&amp;gt; if possible.  The message will consist of all user messages from the entire trace and will have parameters substituted.&lt;br /&gt;
&lt;br /&gt;
{{Example|  Given &amp;lt;vp&amp;gt;raise_cannotCreate&amp;lt;/vp&amp;gt; from above and calling &amp;lt;vp&amp;gt;test&amp;lt;/vp&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;vip&amp;gt;clauses&lt;br /&gt;
    test() :-&lt;br /&gt;
        try&lt;br /&gt;
            raise_cannotCreate(&amp;quot;test.xxx&amp;quot;)&lt;br /&gt;
         catch TraceId do&lt;br /&gt;
            if UserMsg = exceptionDump::tryGetUserMessage(TraceId) then&lt;br /&gt;
                stdio::write(UserMsg)&lt;br /&gt;
            end if&lt;br /&gt;
         end try.&amp;lt;/vip&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The following message is written to &amp;lt;vp&amp;gt;stdio&amp;lt;/vp&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;text&amp;quot;&amp;gt;It is not possible to create the file test.xxx&amp;lt;/source&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== Definite user errors ===&lt;br /&gt;
&lt;br /&gt;
Definite user errors are exceptions that are solely the responsibility of the user of the program.  For example wrong use of the program.&lt;br /&gt;
&lt;br /&gt;
{{Example| A program can write out some information, but only if the user has specified which information to write.  So if the user invoke the functionality without having specified which information to write, it is appropriate to raise a definite user error.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
A definite user exception is distinguished by adding &amp;lt;vp&amp;gt;true&amp;lt;/vp&amp;gt; as extra info for the parameter &amp;lt;vp&amp;gt;common_exception::definiteUserError_parameter&amp;lt;/vp&amp;gt;.  The preferred way to do this is by using the predicates:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;vp&amp;gt;common_exception::raise_definiteUser&amp;lt;/vp&amp;gt;&lt;br /&gt;
* &amp;lt;vp&amp;gt;common_exception::continue_definiteUser&amp;lt;/vp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The use of these predicates is the same as the user of &amp;lt;vp&amp;gt;common_exception::raise_user&amp;lt;/vp&amp;gt; and &amp;lt;vp&amp;gt;common_exception::continue_user&amp;lt;/vp&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
An exception trace is considered a definite user error if one (or more) entries in the trace carries the &amp;lt;vp&amp;gt;common_exception::definiteUserError_parameter&amp;lt;/vp&amp;gt;.  The predicate &amp;lt;vp&amp;gt;common_exception::isDefiniteUserError&amp;lt;/vp&amp;gt; will succeed for definite user errors.&lt;br /&gt;
&lt;br /&gt;
=== Packed Exceptions ===&lt;br /&gt;
&lt;br /&gt;
Some times, e.g., in a client/server application, you catch an exception on the server which you want to handle on the client. In that case you can serialize the exception on the server send it to the client and reraise it as a packed exception.&lt;br /&gt;
&lt;br /&gt;
On the server&lt;br /&gt;
&amp;lt;vip&amp;gt;&lt;br /&gt;
try&lt;br /&gt;
   ...&lt;br /&gt;
catch E do&lt;br /&gt;
   sendExceptionToClient(exception::getTraceInfo())&lt;br /&gt;
end try,&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/vip&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On the client&lt;br /&gt;
&amp;lt;vip&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
Rtn = remoteCall(...),&lt;br /&gt;
if Rtn = error(ExceptionInfo) then&lt;br /&gt;
    common_exception::raise_packed(ExceptionInfo, classInfo, predicate_name(),&amp;quot;remoteCall returned an exception&amp;quot;)&lt;br /&gt;
end if&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/vip&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The predicate raise_packed works like a continue_unknown but continues a serialized exception instead of normal exception. It is meant to be used when the exception stem from another program and thus only is available in serialized form.&lt;br /&gt;
&lt;br /&gt;
== The error presentation dialog  ==&lt;br /&gt;
&lt;br /&gt;
The error presentation dialog (in the class &amp;lt;vp&amp;gt;errorPresentationDialog&amp;lt;/vp&amp;gt;) is by default used by the default exception handling in a GUI program.  Its behavior is closely related to the classification of exceptions described above, as described by these two rules:&lt;br /&gt;
&lt;br /&gt;
* If the exception trace carries a user message, this message will be presented to the user.&lt;br /&gt;
* If the exception trace is not a definite user error, there will be information for the programmer&lt;br /&gt;
&lt;br /&gt;
So if the exception is an internal error there will only be information for the programmer; if it is a user exception there will both be information for the user and for the programmer; and if it is a user error there will only be information for the user.&lt;br /&gt;
&lt;br /&gt;
If there is information to the programmer the exception dialog will have a details/less details button that can show/hide the programmer information.  It will also have a &amp;quot;report error&amp;quot; button, which by default will copy the information to the clipboard so that the user can easily send it to the programmer.&lt;br /&gt;
&lt;br /&gt;
[[Image:ErrorPresentationDialogDefault.png]]&lt;br /&gt;
&lt;br /&gt;
The dialog is customizable by means of various properties:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;vip&amp;gt;properties&lt;br /&gt;
    title : string. % := &amp;quot;Error&amp;quot;.&lt;br /&gt;
    callBackBtnText : string. % := &amp;quot;&amp;amp;Copy&amp;quot;.&lt;br /&gt;
    dontCallBackBtnText : string. % := &amp;quot;&amp;amp;OK&amp;quot;.&lt;br /&gt;
    showDetailsBtnText : string. % := &amp;quot;Show &amp;amp;Details&amp;quot;.&lt;br /&gt;
    hideDetailsBtnText : string. % := &amp;quot;Hide &amp;amp;Details&amp;quot;.&lt;br /&gt;
    closeApplicationBtnText : string. % := &amp;quot;Close &amp;amp;Application&amp;quot;.&lt;br /&gt;
    commentTextPromt : string. % := &amp;quot;Please describe what you were doing when the error occured:&amp;quot;&lt;br /&gt;
    internalErrorMessage : string. %  := &amp;quot;An internal error has occurred.\nPlease send a bug report to your vendor.&amp;quot;.&lt;br /&gt;
    feedbackMessage : string. %  := &amp;quot;Please send your feedback.&amp;quot;.&lt;br /&gt;
    definiteUserErrorIcon : vpiDomains::resid.&lt;br /&gt;
    userErrorIcon : vpiDomains::resid.&lt;br /&gt;
    internalErrorIcon : vpiDomains::resid.&lt;br /&gt;
    reportErrorDelegate : reportErrorDelegate.&lt;br /&gt;
    extraInfoWriter : writer.&amp;lt;/vip&amp;gt;&lt;br /&gt;
&lt;br /&gt;
All texts and labels are controlled by properties. &lt;br /&gt;
&lt;br /&gt;
The &amp;lt;vp&amp;gt;extraInfoWriter&amp;lt;/vp&amp;gt; is a callback that can be set to include extra info for the programmer.  This information will both be presented in the details window and reported back to the programmer if the user press the &amp;quot;report error&amp;quot; button (i.e. the button which is by default labeled &amp;#039;&amp;#039;&amp;#039;Copy&amp;#039;&amp;#039;&amp;#039;).&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;vp&amp;gt;extraInfoWriter&amp;lt;/vp&amp;gt; callback predicate must have this type:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;vip&amp;gt;domains&lt;br /&gt;
    writer = (outputStream Stream).&amp;lt;/vip&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The dialog will invoke the predicate and then it should simply write extra information to the received stream.&lt;br /&gt;
&lt;br /&gt;
{{Example| The Visual Prolog IDE uses the &amp;lt;vp&amp;gt;extraInfoWriter&amp;lt;/vp&amp;gt; to write version information, information about the open project and information about the last actions carried out in the IDE.  This information will help the programmers to analyze the problem.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
The action performed by the &amp;quot;report error&amp;quot; button is customizable using the property &amp;lt;vp&amp;gt;reportErrorDelegate&amp;lt;/vp&amp;gt;, which is a callback predicate of this type:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;vip&amp;gt;domains&lt;br /&gt;
    reportErrorDelegate = (window Parent, string Comment, optional{exception::traceInfo} TraceInfo, string ExtraInfo).&amp;lt;/vip&amp;gt;&lt;br /&gt;
&lt;br /&gt;
; &amp;lt;vp&amp;gt;Parent&amp;lt;/vp&amp;gt;&lt;br /&gt;
: The error presentation dialog which can be used as parent for additional dialogs.&lt;br /&gt;
; &amp;lt;vp&amp;gt;Comment&amp;lt;/vp&amp;gt;&lt;br /&gt;
: The users comment from the comment box.&lt;br /&gt;
; &amp;lt;vp&amp;gt;TraceInfo&amp;lt;/vp&amp;gt;&lt;br /&gt;
: If the dialog is invoked on an exception the trace info is here, if it is invoked for feedback this value is &amp;lt;vp&amp;gt;none&amp;lt;/vp&amp;gt;&lt;br /&gt;
; &amp;lt;vp&amp;gt;ExtraInfo&amp;lt;/vp&amp;gt;&lt;br /&gt;
: The extra info written by the &amp;lt;vp&amp;gt;extraInfoWriter&amp;lt;/vp&amp;gt; callback&lt;br /&gt;
&lt;br /&gt;
{{Example| In the Visual Prolog IDE the &amp;lt;vp&amp;gt;reportErrorDelegate&amp;lt;/vp&amp;gt; will send the exception information to a WEB service which will insert the notification in a database.  The notifications in the database will then be used to improve the IDE.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
[[Category:Tutorials]]&lt;/div&gt;</summary>
		<author><name>Kehler</name></author>
	</entry>
	<entry>
		<id>https://wiki.visual-prolog.com/index.php?title=Calling_C_Sharp_via_COM&amp;diff=1743</id>
		<title>Calling C Sharp via COM</title>
		<link rel="alternate" type="text/html" href="https://wiki.visual-prolog.com/index.php?title=Calling_C_Sharp_via_COM&amp;diff=1743"/>
		<updated>2009-02-20T10:55:33Z</updated>

		<summary type="html">&lt;p&gt;Kehler: /* Further info about .Net COM integration */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Howto call C# ==&lt;br /&gt;
&lt;br /&gt;
This tutorial gives a description of one way of accessing C# from prolog.&lt;br /&gt;
&lt;br /&gt;
We make the C# library COM visible and then we import the COM component in visual prolog.&lt;br /&gt;
&lt;br /&gt;
=== Creating a C# COM component in Visual Studio ===&lt;br /&gt;
&lt;br /&gt;
# Create a C# project. I just created one that was a class library.&lt;br /&gt;
# Open the project properties. Open the assembly information. Select ‘Make Assembly Com-Visible’.&lt;br /&gt;
# Make an interface that expose the functions you want to call and a class that implements that interface.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
For the interface set the attributes InterfaceType ot InterfaceIsIUnknown and a GuidAttribute to some GUID (generated by tools\Create GUID in VS)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;csharp&amp;quot;&amp;gt;&lt;br /&gt;
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown),&lt;br /&gt;
GuidAttribute(&amp;quot;0828DB14-1275-3926-813D-494F4FE771CF&amp;quot;)]&lt;br /&gt;
public interface IMyInterface&lt;br /&gt;
{&lt;br /&gt;
    string MyFunction(string Input);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The ClassInterface should be None and here should also be a GuidAttribute.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;csharp&amp;quot;&amp;gt;&lt;br /&gt;
[ClassInterface(ClassInterfaceType.None),&lt;br /&gt;
GuidAttribute(&amp;quot;95E62F78-55FF-4061-8238-6D3FCF88F5D0&amp;quot;)]&lt;br /&gt;
public class MyClass : IMyInterface&lt;br /&gt;
{&lt;br /&gt;
     …&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Remember to add:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;csharp&amp;quot;&amp;gt;&lt;br /&gt;
using System.Runtime.InteropServices;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Compile the program.&lt;br /&gt;
&lt;br /&gt;
=== Importing the COM component in Visual Prolog ===&lt;br /&gt;
&lt;br /&gt;
Copy assembly dll to your prolog projects exe folder.&lt;br /&gt;
&lt;br /&gt;
If it has to be placed somewhere else there is some work with the registration which have to use /codebase, currently we expect it to be placed in the exe folder&lt;br /&gt;
&lt;br /&gt;
Run tlbexp.exe on the dll to get a xxx.tbl file tlpexp.exe comes together with the windows SDK.&lt;br /&gt;
&lt;br /&gt;
Register the dll using regasm.exe (this has to be done every time the program have to run on a new machine).&lt;br /&gt;
&lt;br /&gt;
Import the COM component into the Visual Prolog project.&lt;br /&gt;
Select &amp;#039;New in new package&amp;#039; in the project tree. Give the package a name and select COM package load the type library (that is the tlb file). &lt;br /&gt;
&lt;br /&gt;
Now the program should be able to run.&lt;br /&gt;
&lt;br /&gt;
=== Further info about .Net COM integration ===&lt;br /&gt;
&lt;br /&gt;
You can find more information here: [http://msdn.microsoft.com/en-us/library/zsfww439.aspx]&lt;br /&gt;
&lt;br /&gt;
[[Category:Tutorials]]&lt;/div&gt;</summary>
		<author><name>Kehler</name></author>
	</entry>
	<entry>
		<id>https://wiki.visual-prolog.com/index.php?title=Calling_C_Sharp_via_COM&amp;diff=1742</id>
		<title>Calling C Sharp via COM</title>
		<link rel="alternate" type="text/html" href="https://wiki.visual-prolog.com/index.php?title=Calling_C_Sharp_via_COM&amp;diff=1742"/>
		<updated>2009-02-20T10:54:52Z</updated>

		<summary type="html">&lt;p&gt;Kehler: New page: == Howto call C# ==  This tutorial gives a description of one way of accessing C# from prolog.  We make the C# library COM visible and then we import the COM component in visual prolog.  =...&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Howto call C# ==&lt;br /&gt;
&lt;br /&gt;
This tutorial gives a description of one way of accessing C# from prolog.&lt;br /&gt;
&lt;br /&gt;
We make the C# library COM visible and then we import the COM component in visual prolog.&lt;br /&gt;
&lt;br /&gt;
=== Creating a C# COM component in Visual Studio ===&lt;br /&gt;
&lt;br /&gt;
# Create a C# project. I just created one that was a class library.&lt;br /&gt;
# Open the project properties. Open the assembly information. Select ‘Make Assembly Com-Visible’.&lt;br /&gt;
# Make an interface that expose the functions you want to call and a class that implements that interface.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
For the interface set the attributes InterfaceType ot InterfaceIsIUnknown and a GuidAttribute to some GUID (generated by tools\Create GUID in VS)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;csharp&amp;quot;&amp;gt;&lt;br /&gt;
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown),&lt;br /&gt;
GuidAttribute(&amp;quot;0828DB14-1275-3926-813D-494F4FE771CF&amp;quot;)]&lt;br /&gt;
public interface IMyInterface&lt;br /&gt;
{&lt;br /&gt;
    string MyFunction(string Input);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The ClassInterface should be None and here should also be a GuidAttribute.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;csharp&amp;quot;&amp;gt;&lt;br /&gt;
[ClassInterface(ClassInterfaceType.None),&lt;br /&gt;
GuidAttribute(&amp;quot;95E62F78-55FF-4061-8238-6D3FCF88F5D0&amp;quot;)]&lt;br /&gt;
public class MyClass : IMyInterface&lt;br /&gt;
{&lt;br /&gt;
     …&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Remember to add:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;csharp&amp;quot;&amp;gt;&lt;br /&gt;
using System.Runtime.InteropServices;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Compile the program.&lt;br /&gt;
&lt;br /&gt;
=== Importing the COM component in Visual Prolog ===&lt;br /&gt;
&lt;br /&gt;
Copy assembly dll to your prolog projects exe folder.&lt;br /&gt;
&lt;br /&gt;
If it has to be placed somewhere else there is some work with the registration which have to use /codebase, currently we expect it to be placed in the exe folder&lt;br /&gt;
&lt;br /&gt;
Run tlbexp.exe on the dll to get a xxx.tbl file tlpexp.exe comes together with the windows SDK.&lt;br /&gt;
&lt;br /&gt;
Register the dll using regasm.exe (this has to be done every time the program have to run on a new machine).&lt;br /&gt;
&lt;br /&gt;
Import the COM component into the Visual Prolog project.&lt;br /&gt;
Select &amp;#039;New in new package&amp;#039; in the project tree. Give the package a name and select COM package load the type library (that is the tlb file). &lt;br /&gt;
&lt;br /&gt;
Now the program should be able to run.&lt;br /&gt;
&lt;br /&gt;
=== Further info about .Net COM integration ===&lt;br /&gt;
&lt;br /&gt;
You can find more information here: [http://msdn.microsoft.com/en-us/library/zsfww439.aspx]&lt;/div&gt;</summary>
		<author><name>Kehler</name></author>
	</entry>
	<entry>
		<id>https://wiki.visual-prolog.com/index.php?title=Exception_Handling&amp;diff=1661</id>
		<title>Exception Handling</title>
		<link rel="alternate" type="text/html" href="https://wiki.visual-prolog.com/index.php?title=Exception_Handling&amp;diff=1661"/>
		<updated>2008-11-23T12:12:39Z</updated>

		<summary type="html">&lt;p&gt;Kehler: /* Packed Exceptions */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;An exception is a deviation from the expected.  What is an exception in one context may be expected in another context, and thus not an exception in that context.&lt;br /&gt;
&lt;br /&gt;
In Visual Prolog programs exceptions are used to deal with deviations from what is expected in the given context.  When a certain program part gets into a situation it cannot deal with it can &amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039;raise&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039; an exception.  When an exception is raised the program control is transferred to the nearest &amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039;exception handler&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039;.  If the exception handler cannot handle the exception it can either raise a new exception or &amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039;continue&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039; the original exception.&lt;br /&gt;
&lt;br /&gt;
The program will terminate with an error message if there is no exception handler to transfer the control to.&lt;br /&gt;
&lt;br /&gt;
== Introduction to exception handling  ==&lt;br /&gt;
&lt;br /&gt;
There are many concepts and entities to understand when dealing with exceptions.  This section will give an introduction by means of an example.&lt;br /&gt;
&lt;br /&gt;
A certain program needs to write some information to a file.  Therefore it has a predicate &amp;lt;vp&amp;gt;writeInfo&amp;lt;/vp&amp;gt; that can write this information.  &amp;lt;vp&amp;gt;writeInfo&amp;lt;/vp&amp;gt; calls the PFC constructor &amp;lt;vp&amp;gt;outputStream_file::create&amp;lt;/vp&amp;gt; to obtain a stream that it can write the information to:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;vip&amp;gt;clauses&lt;br /&gt;
    writeInfo(Filename) :-&lt;br /&gt;
        S = outputStream_file::create(Filename),&lt;br /&gt;
        …&amp;lt;/vip&amp;gt;&lt;br /&gt;
&lt;br /&gt;
But if the file already exists and is write-protected it is impossible to create the stream.&lt;br /&gt;
&lt;br /&gt;
In &amp;lt;vp&amp;gt;outputStream_file::create&amp;lt;/vp&amp;gt; this situation is considered to be exceptional/unexpected and therefore it raises an exception.&lt;br /&gt;
&lt;br /&gt;
When an exception is raised the program control is transferred to the nearest exception handler, which can hopefully handle the situation and thus bring the program back on track again.&lt;br /&gt;
&lt;br /&gt;
In this case &amp;lt;vp&amp;gt;writeInfo&amp;lt;/vp&amp;gt; is called after the user have entered the file name in a dialog and pressed a &amp;#039;&amp;#039;&amp;#039;Save&amp;#039;&amp;#039;&amp;#039;-button.  So the handling we want is simply to tell the user that the information was not written because the file was write-protected.  The user can choose a different filename, remove the write protection, delete the file, cancel the operation entirely or something else.  But from the program&amp;#039;s point of view the exceptional situation is handled.&lt;br /&gt;
&lt;br /&gt;
To set a handler we use the {{lang2|Terms|try-catch|try-catch}} language construction:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;vip&amp;gt;clauses&lt;br /&gt;
    saveInfo(Filename) :-&lt;br /&gt;
        try&lt;br /&gt;
            writeInfo(Filename)&lt;br /&gt;
         catch TraceId do&lt;br /&gt;
              % &amp;lt;&amp;lt;handle situation&amp;gt;&amp;gt;&lt;br /&gt;
         end try.&amp;lt;/vip&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The code works like this:  &amp;lt;vp&amp;gt;writeInfo&amp;lt;/vp&amp;gt; is called, if it succeeds the {{lang2|Terms|try-catch|try-catch}} construction will not do more and &amp;lt;vp&amp;gt;saveInfo&amp;lt;/vp&amp;gt; will also succeed.&lt;br /&gt;
&lt;br /&gt;
But in the write-protected case &amp;lt;vp&amp;gt;outputStream_file::create&amp;lt;/vp&amp;gt; will raise an exception and therefore the following will take place:&lt;br /&gt;
&lt;br /&gt;
# &amp;lt;vp&amp;gt;TraceId&amp;lt;/vp&amp;gt; will be bound to the (so called) &amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039;trace id&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039;, which is a handle to information about the exception (described in more details below)&lt;br /&gt;
# The handler code (i.e. the code between &amp;lt;vp&amp;gt;do&amp;lt;/vp&amp;gt; and &amp;lt;vp&amp;gt;end try&amp;lt;/vp&amp;gt;) is evaluated&lt;br /&gt;
# The result of the handler code will be the result of the {{lang2|Terms|try-catch|try-catch}} construction, and thus of &amp;lt;vp&amp;gt;saveInfo&amp;lt;/vp&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
So for the &amp;quot;write-protected&amp;quot; exception the handler code should write a message to the user.&lt;br /&gt;
&lt;br /&gt;
If it is another kind of exception the handler will have to do something different.  Especially, it may be an exception that the handler does not know how to handle.  In this case the best thing the handler code can do is to continue the exception as an &amp;#039;&amp;#039;unknown&amp;#039;&amp;#039; exception (i.e. unknown to the handler).&lt;br /&gt;
&lt;br /&gt;
When an exception is continued it consists of the original exception plus some continue information.  If it has been continued by several handlers it will contain a lot of continue information in addition to the original exception information.  The exception information describes a trace from the point of raise through all the handlers.  The &amp;lt;vp&amp;gt;TraceId&amp;lt;/vp&amp;gt; variable that is bound in the {{lang2|Terms|try-catch|try-catch}} construction gives access information about the entire trace (hence the name).&lt;br /&gt;
&lt;br /&gt;
As mentioned above the program will terminate with en error message, if an exception is raised and no handler can be found.  Therefore programs normally setup an outermost default exception handler.  &amp;lt;vp&amp;gt;mainExe::run&amp;lt;/vp&amp;gt; setup such a handler in a console program this is the fall-back handler.  In a GUI program there is also a default hander in the GUI event loop which will catch exceptions arising from the handling of an event.&lt;br /&gt;
&lt;br /&gt;
All in all, the lifecycle of an exception is as follows:&lt;br /&gt;
&lt;br /&gt;
* It is raised&lt;br /&gt;
* It is caught and continued&lt;br /&gt;
* It is caught and continued&lt;br /&gt;
* …&lt;br /&gt;
* It is caught and handled (or the program terminates with an error message)&lt;br /&gt;
&lt;br /&gt;
Each time the exception is caught the trace so far can be examined.  When the exception is raised and each time it is continued extra information can be added to the exception trace.  If nothing else handles an exception it will (normally) be handled by the fallback/default handler of the program.&lt;br /&gt;
&lt;br /&gt;
== Defining an exception ==&lt;br /&gt;
&lt;br /&gt;
An exception is a value of the type &amp;lt;vp&amp;gt;core::exception&amp;lt;/vp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;vip&amp;gt;domains&lt;br /&gt;
    exception = (classInfo ClassInfo [out], string PredicateName [out], string Description [out]).&amp;lt;/vip&amp;gt;&lt;br /&gt;
&lt;br /&gt;
I.e. an exception is a predicate that returns three pieces of information:&lt;br /&gt;
&lt;br /&gt;
; &amp;lt;vp&amp;gt;ClassInfo&amp;lt;/vp&amp;gt;&lt;br /&gt;
: The &amp;lt;vp&amp;gt;classInfo&amp;lt;/vp&amp;gt; of the class that defines the exception&lt;br /&gt;
; &amp;lt;vp&amp;gt;PredicateName&amp;lt;/vp&amp;gt;&lt;br /&gt;
: The name of the exception predicate itself&lt;br /&gt;
; &amp;lt;vp&amp;gt;Description&amp;lt;/vp&amp;gt;&lt;br /&gt;
: A description of the exception&lt;br /&gt;
&lt;br /&gt;
{{example| The &amp;lt;vp&amp;gt;cannotCreate&amp;lt;/vp&amp;gt; exception from the example above is declared in the class &amp;lt;vp&amp;gt;fileSystem_api&amp;lt;/vp&amp;gt; like this:&lt;br /&gt;
&amp;lt;vip&amp;gt;class fileSystem_api&lt;br /&gt;
…&lt;br /&gt;
predicates&lt;br /&gt;
    cannotCreate : exception.&lt;br /&gt;
…&amp;lt;/vip&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The implementation looks like this:&lt;br /&gt;
&amp;lt;vip&amp;gt;impement	 fileSystem_api&lt;br /&gt;
…&lt;br /&gt;
clauses&lt;br /&gt;
    cannotCreate(classInfo, predicate_name(), &amp;quot;Cannot create or open the specified file&amp;quot;).&lt;br /&gt;
…&amp;lt;/vip&amp;gt;&lt;br /&gt;
&amp;lt;vp&amp;gt;classInfo&amp;lt;/vp&amp;gt; is the &amp;lt;vp&amp;gt;classInfo&amp;lt;/vp&amp;gt; of the &amp;lt;vp&amp;gt;fileSystem_api&amp;lt;/vp&amp;gt; class ; &amp;lt;vp&amp;gt;predicate_name&amp;lt;/vp&amp;gt; is a built-in predicate  that returns the name of the predicate in which it is called (i.e. in this case it will return &amp;lt;vp&amp;gt;&amp;quot;cannotCreate&amp;quot;&amp;lt;/vp&amp;gt;).  The last argument is the description of the exception. &lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Many/most programmers will never need to define exceptions, because in many/most cases the exceptions to use are already defined.  An exception definition is only needed when the exception must be distinguished from other kinds of exceptions, such that exception handlers can deal specially with that kind of exception.  Typically exception definitions are only necessary for exceptions that are raised by library software.  I most cases programmers will raise the exception &amp;lt;vp&amp;gt;internal_error&amp;lt;/vp&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Raising an exception ==&lt;br /&gt;
&lt;br /&gt;
Exceptions are raised using the predicate &amp;lt;vp&amp;gt;exception::raise&amp;lt;/vp&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;vip&amp;gt;class exception&lt;br /&gt;
…&lt;br /&gt;
predicates&lt;br /&gt;
    raise : (classInfo ClassInfo, exception Exception) erroneous. &lt;br /&gt;
    raise : (classInfo ClassInfo, exception Exception, namedValue_list ExtraInfo) erroneous.&amp;lt;/vip&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;vp&amp;gt;ClassInfo&amp;lt;/vp&amp;gt;&lt;br /&gt;
: The &amp;lt;vp&amp;gt;classInfo&amp;lt;/vp&amp;gt; of the class that raise the excption&lt;br /&gt;
&amp;lt;vp&amp;gt;Exception&amp;lt;/vp&amp;gt;&lt;br /&gt;
: The exception to raise&lt;br /&gt;
&amp;lt;vp&amp;gt;ExtraInfo&amp;lt;/vp&amp;gt;&lt;br /&gt;
: Extra information about the raised exception.&lt;br /&gt;
&lt;br /&gt;
{{example|The &amp;lt;vp&amp;gt;cannotCreate&amp;lt;/vp&amp;gt; exception from above is raised by the predicate &amp;lt;vp&amp;gt;fileSystem_api::raise_cannotCreate&amp;lt;/vp&amp;gt;. The code  looks like this:&lt;br /&gt;
&amp;lt;vip&amp;gt;clauses&lt;br /&gt;
    raise_cannotCreate(ClassInfo, FileName, LastError) :-&lt;br /&gt;
        Desc = common_exception::getLastErrorDescription(LastError),&lt;br /&gt;
        exception::raise(&lt;br /&gt;
            ClassInfo,&lt;br /&gt;
            cannotCreate,&lt;br /&gt;
            [namedValue(fileSystem_exception::fileName_parameter, string(FileName)),&lt;br /&gt;
             namedValue(common_exception::errorCode_parameter, unsigned(LastError)),&lt;br /&gt;
             namedValue(common_exception::errorDescription_parameter, string(Desc))]).&amp;lt;/vip&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;vp&amp;gt;raise_cannotCreate&amp;lt;/vp&amp;gt; is called with the &amp;lt;vp&amp;gt;ClassInfo&amp;lt;/vp&amp;gt; of the raising class the &amp;lt;vp&amp;gt;FileName&amp;lt;/vp&amp;gt; and the windows error code &amp;lt;vp&amp;gt;LastError&amp;lt;/vp&amp;gt; that the relevant low level Windows API predicate caused.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;vp&amp;gt;common_exception::getLastErrorDescription&amp;lt;/vp&amp;gt; obtains the description corresponding to &amp;lt;vp&amp;gt;LastError&amp;lt;/vp&amp;gt; from Windows.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;vp&amp;gt;exception::raise&amp;lt;/vp&amp;gt; is then used to raise the &amp;lt;vp&amp;gt;cannotCreate&amp;lt;/vp&amp;gt; exception with the three pieces of extra information.   &amp;lt;vp&amp;gt;fileSystem_exception::fileName_parameter&amp;lt;/vp&amp;gt;, &amp;lt;vp&amp;gt;common_exception::errorCode_parameter&amp;lt;/vp&amp;gt; and &amp;lt;vp&amp;gt;common_exception::errorDescription_parameter&amp;lt;/vp&amp;gt; are names (strings) used for the extra information. &lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
It is very common to create helper predicates like  &amp;lt;vp&amp;gt;fileSystem_api::raise_cannotCreate&amp;lt;/vp&amp;gt; to do the actual raising rather that calling &amp;lt;vp&amp;gt;exception::raise&amp;lt;/vp&amp;gt; directly from the code that needs to raise the exception.  That way it is certain that the extra info for this particular exception is handled in the same way in all cases.&lt;br /&gt;
&lt;br /&gt;
Normally the helper raise predicate is created by the same programmer that declares the exception.  And as mentioned above this is normally only programmers that create library software.&lt;br /&gt;
&lt;br /&gt;
Application programmers will in most cases raise exceptions by calling appropriate raiser predicates, typically the ones defined in &amp;lt;vp&amp;gt;common_exception&amp;lt;/vp&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Catching and handling exceptions ==&lt;br /&gt;
&lt;br /&gt;
Exceptions are caught with the {{lang2|Terms|try-catch|try-catch}} construction:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;vipbnf&amp;gt;try &amp;lt;Body&amp;gt; catch &amp;lt;TraceId&amp;gt; do &amp;lt;Handler&amp;gt; end try&amp;lt;/vipbnf&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If &amp;lt;vpbnf&amp;gt;&amp;lt;Body&amp;gt;&amp;lt;/vpbnf&amp;gt; terminates with an exception &amp;lt;vpbnf&amp;gt;&amp;lt;TraceId&amp;gt;&amp;lt;/vpbnf&amp;gt; is bound to the &amp;#039;&amp;#039;trace id&amp;#039;&amp;#039; and then &amp;lt;vpbnf&amp;gt;&amp;lt;Handler&amp;gt;&amp;lt;/vpbnf&amp;gt; is evaluated.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;vpbnf&amp;gt;&amp;lt;TraceId&amp;gt;&amp;lt;/vpbnf&amp;gt; is used to obtain information about the exception trace.  This information can be used for at least two things:&lt;br /&gt;
&lt;br /&gt;
* Determine which kind of exception that is caught, so that it can be decided if and how to handle it&lt;br /&gt;
* Obtain additional information to write to the user, in a log or use for something else&lt;br /&gt;
&lt;br /&gt;
You will call &amp;lt;vp&amp;gt;exception::tryGetDescriptor&amp;lt;/vp&amp;gt; to determine if a certain kind of exception is caught:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;vip&amp;gt;predicates&lt;br /&gt;
    tryGetDescriptor : (traceId TraceID, exception Exception) -&amp;gt; descriptor Descriptor determ.&amp;lt;/vip&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The exception trace corresponding to &amp;lt;vp&amp;gt;TraceId&amp;lt;/vp&amp;gt; is searched for an exception of the kind &amp;lt;vp&amp;gt;Exception&amp;lt;/vp&amp;gt;.  If there is such an entry in the trace (raised or continued) a corresponding exception descriptor is returned in &amp;lt;vp&amp;gt;Descriptor&amp;lt;/vp&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The predicate fails if such an exception is not in the exception trace.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;vp&amp;gt;Descriptor&amp;lt;/vp&amp;gt; contains the extra information about that particular entry in the exception trace:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;vip&amp;gt;domains&lt;br /&gt;
    descriptor = descriptor(classInfoDescriptor ClassInfo, exceptionDescriptor ExceptionInfo, kind Kind,&lt;br /&gt;
        namedValue_list ExtraInfo, gmtTimeValue GMTTime, string ExceptionDescription, unsigned ThreadId).&amp;lt;/vip&amp;gt;&lt;br /&gt;
&lt;br /&gt;
; &amp;lt;vp&amp;gt;ClassInfo&amp;lt;/vp&amp;gt;&lt;br /&gt;
: The &amp;lt;vp&amp;gt;classInfo&amp;lt;/vp&amp;gt; of the class that raised the exception (in functor form)&lt;br /&gt;
; &amp;lt;vp&amp;gt;ExceptionInfo&amp;lt;/vp&amp;gt;&lt;br /&gt;
: The &amp;lt;vp&amp;gt;exception&amp;lt;/vp&amp;gt; in question (in functor form)&lt;br /&gt;
; &amp;lt;vp&amp;gt;Kind&amp;lt;/vp&amp;gt;&lt;br /&gt;
: The entry kind (&amp;lt;vp&amp;gt;raise&amp;lt;/vp&amp;gt; or &amp;lt;vp&amp;gt;continue&amp;lt;/vp&amp;gt;)&lt;br /&gt;
; &amp;lt;vp&amp;gt;ExtraInfo&amp;lt;/vp&amp;gt;&lt;br /&gt;
: The extra information provided with this entry in the trace&lt;br /&gt;
; &amp;lt;vp&amp;gt;GMTTime&amp;lt;/vp&amp;gt;&lt;br /&gt;
: The time this exception trace entry was raised/continued&lt;br /&gt;
; &amp;lt;vp&amp;gt;ExceptionDescription&amp;lt;/vp&amp;gt;&lt;br /&gt;
: The exception description of this entry (this information is also present in &amp;lt;vp&amp;gt;ExceptionInfo&amp;lt;/vp&amp;gt;)&lt;br /&gt;
; &amp;lt;vp&amp;gt;ThreadId&amp;lt;/vp&amp;gt;&lt;br /&gt;
: The thread id of the thread that raised/continued this entry&lt;br /&gt;
&lt;br /&gt;
Much of this information is mainly interesting if the exception is not handled.  The information that is most interesting when handling an exception is:&lt;br /&gt;
&lt;br /&gt;
* The exception kind has been determined to be the one we expected&lt;br /&gt;
* The &amp;lt;vp&amp;gt;ExtraInfo&amp;lt;/vp&amp;gt; for this entry is available for use in messages, etc&lt;br /&gt;
&lt;br /&gt;
The predicate &amp;lt;vp&amp;gt;exception::tryGetExtraInfo&amp;lt;/vp&amp;gt; is convenient for obtaining extra information:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;vip&amp;gt;predicates&lt;br /&gt;
    tryGetExtraInfo : (descriptor Descriptor, string Name) -&amp;gt; value Value determ.&amp;lt;/vip&amp;gt;&lt;br /&gt;
&lt;br /&gt;
; &amp;lt;vp&amp;gt;Descriptor&amp;lt;/vp&amp;gt;&lt;br /&gt;
: Is the description whose extra info we want to get something from.&lt;br /&gt;
; &amp;lt;vp&amp;gt;Name&amp;lt;/vp&amp;gt;&lt;br /&gt;
: The name of the extra info parameter we want to obtain.&lt;br /&gt;
; &amp;lt;vp&amp;gt;Value&amp;lt;/vp&amp;gt;&lt;br /&gt;
: The value that the mentioned parameter has.&lt;br /&gt;
&lt;br /&gt;
{{example|  Code for catching and handling the &amp;lt;vp&amp;gt;fileSystem_api::cannotCreate&amp;lt;/vp&amp;gt; exception can look like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;vip&amp;gt;clauses&lt;br /&gt;
    saveInfo(Filename) :-&lt;br /&gt;
        try&lt;br /&gt;
            writeInfo(Filename)&lt;br /&gt;
         catch TraceId do&lt;br /&gt;
              if D = exception::tryGetDescriptor(TraceId, fileSystem_api::cannotCreate) then&lt;br /&gt;
                stdio::write(&amp;quot;Cannot write to the file: &amp;quot;, Filename),&lt;br /&gt;
                if string(Description) = exception::tryGetExtraInfo(D, common_exception::errorDescription_parameter) then&lt;br /&gt;
                    stdio::writef(&amp;quot;; %&amp;quot;, Description)&lt;br /&gt;
                end if,&lt;br /&gt;
                stdio::write(&amp;quot;\n&amp;quot;)&lt;br /&gt;
            else&lt;br /&gt;
                common_exception::continue_unknown(TraceId, classInfo, predicate_name(), &amp;quot;Filename = &amp;quot;, Filename)&lt;br /&gt;
            end if&lt;br /&gt;
         end try.&amp;lt;/vip&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The code here don&amp;#039;t need to obtain the &amp;lt;vp&amp;gt;fileSystem_exception::fileName_parameter&amp;lt;/vp&amp;gt;, because the file name is already known in the &amp;lt;vp&amp;gt;Filename&amp;lt;/vp&amp;gt; variable.&lt;br /&gt;
&lt;br /&gt;
But we can obtain Window&amp;#039;s description of the problem querying for &amp;lt;vp&amp;gt;common_exception::errorDescription_parameter&amp;lt;/vp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We &amp;#039;&amp;#039;&amp;#039;continue&amp;#039;&amp;#039;&amp;#039; the exception as unknown if it is not the &amp;lt;vp&amp;gt;cannotCreate&amp;lt;/vp&amp;gt; kind .  For the continue call we add the filename as.  &amp;lt;vp&amp;gt;common_exception::continue_unknown&amp;lt;/vp&amp;gt; will create a string of the extra arguments and add it as an &amp;lt;vp&amp;gt;common_exception::errorArguments_parameter&amp;lt;/vp&amp;gt;.  Such information is mainly for use in the default exception handler to be discussed below. &lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== Serializing exceptions ==&lt;br /&gt;
&lt;br /&gt;
In some situations the best way to handle  an exception is by sending all the information about the exception somewhere else.  A server might for example want to send the information to the client program that caused the exception, because then there is a user that can take action.&lt;br /&gt;
&lt;br /&gt;
A &amp;lt;vp&amp;gt;traceId&amp;lt;/vp&amp;gt; only have a meaning in the process that has created it, but the predicate &amp;lt;vp&amp;gt;exception::getTraceInfo&amp;lt;/vp&amp;gt; can create a &amp;lt;vp&amp;gt;traceInfo&amp;lt;/vp&amp;gt; structure (&amp;lt;vp&amp;gt;TraceInfo&amp;lt;/vp&amp;gt;) from the &amp;lt;vp&amp;gt;traceId TraceId&amp;lt;/vp&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;vip&amp;gt;predicates&lt;br /&gt;
    getTraceInfo : (traceId TraceId) -&amp;gt; traceInfo TraceInfo.&amp;lt;/vip&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Such a structure is a functor structure that can be serialized/deserialized with &amp;lt;vp&amp;gt;toString&amp;lt;/vp&amp;gt;/&amp;lt;vp&amp;gt;toTerm&amp;lt;/vp&amp;gt;; &amp;lt;vp&amp;gt;write&amp;lt;/vp&amp;gt;/&amp;lt;vp&amp;gt;read&amp;lt;/vp&amp;gt;; nested in a fact database using &amp;lt;vp&amp;gt;save&amp;lt;/vp&amp;gt;/&amp;lt;vp&amp;gt;consult&amp;lt;/vp&amp;gt;; etc.&lt;br /&gt;
&lt;br /&gt;
== Exception dumps ==&lt;br /&gt;
&lt;br /&gt;
The class &amp;lt;vp&amp;gt;exceptionDump&amp;lt;/vp&amp;gt; contains predicates for dumping exception traces to &amp;lt;vp&amp;gt;stdio&amp;lt;/vp&amp;gt;, some other &amp;lt;vp&amp;gt;outputStream&amp;lt;/vp&amp;gt; or a &amp;lt;vp&amp;gt;string&amp;lt;/vp&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
An exception dump contains three major pieces of information:&lt;br /&gt;
&lt;br /&gt;
* A dump of the call stack (with file names and line numbers) from the point where the exception was raised&lt;br /&gt;
* A dump of the exception-trace with all the information from the exception descriptors&lt;br /&gt;
* Information about the operating system that the program ran on&lt;br /&gt;
 &lt;br /&gt;
&amp;lt;vp&amp;gt;exceptionDump&amp;lt;/vp&amp;gt; have predicates both for dumping exception traces both from a &amp;lt;vp&amp;gt;traceId&amp;lt;/vp&amp;gt; and from a &amp;lt;vp&amp;gt;traceInfo&amp;lt;/vp&amp;gt; obtained with &amp;lt;vp&amp;gt;exception::getTraceInfo&amp;lt;/vp&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Dumps for a certain program are in general only useful to the programmers of that program; the users of the program will find dumps cryptic and rather uninteresting.  I.e. the purpose of dumps is to give the programmer means for improving the program.&lt;br /&gt;
&lt;br /&gt;
== Default handling ==&lt;br /&gt;
&lt;br /&gt;
A program should handle all exceptions, because if an exception is continued or raised at a point where there is no handler the program will terminate with a rather bad error message.  The error message is bad because most exception handling is done in PFC; the language itself knows nothing about exception traces and the like.&lt;br /&gt;
&lt;br /&gt;
To be sure that all exceptions are handled it is normal to set up a default (or fallback) exception handler.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;vp&amp;gt;mainExe::run&amp;lt;/vp&amp;gt; (and &amp;lt;vp&amp;gt;mainExe::runCom&amp;lt;/vp&amp;gt;) which is normally called in the goal setup such a default exception handler: It runs the &amp;lt;vp&amp;gt;main::run&amp;lt;/vp&amp;gt; predicate inside a {{lang2|Terms|try-catch|try-catch}} construction that will handle any exception.&lt;br /&gt;
&lt;br /&gt;
The handler in &amp;lt;vp&amp;gt;mainExe::run&amp;lt;/vp&amp;gt; (and &amp;lt;vp&amp;gt;mainExe::runCom&amp;lt;/vp&amp;gt;) dumps the entire exception trace to output stream in &amp;lt;vp&amp;gt;stdio&amp;lt;/vp&amp;gt;.  And then the program will terminate.  The idea is that:&lt;br /&gt;
&lt;br /&gt;
* Perhaps the user can see something from the dump (which may for example say that &amp;#039;&amp;#039;access is denied&amp;#039;&amp;#039; to &amp;#039;&amp;#039;xxx.txt&amp;#039;&amp;#039;)&lt;br /&gt;
* Alternatively, the developer of the program may use the dump to improve the program&lt;br /&gt;
&lt;br /&gt;
In addition to the handler in &amp;lt;vp&amp;gt;mainExe::run&amp;lt;/vp&amp;gt; a GUI program also set a default handler in the event loop.  This handler is set by calling &amp;lt;vp&amp;gt;applicationWindow::setErrorResponder&amp;lt;/vp&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;vip&amp;gt;domains&lt;br /&gt;
    errorResponder = (applicationWindow Source, exception::traceId TraceId).&lt;br /&gt;
&lt;br /&gt;
predicates&lt;br /&gt;
    setErrorResponder : (errorResponder Responder).&amp;lt;/vip&amp;gt;&lt;br /&gt;
&lt;br /&gt;
By default the error responder &amp;lt;vp&amp;gt;errorPresentationDialog::present&amp;lt;/vp&amp;gt; is used.  The functioning of the &amp;lt;pv&amp;gt;errorPresentationDialog&amp;lt;/vp&amp;gt; is closely related to a categorization of exceptions described in the next section.&lt;br /&gt;
&lt;br /&gt;
PFC place exceptions in three major categories based on who is (believed to be) responsible:&lt;br /&gt;
&lt;br /&gt;
; Internal errors&lt;br /&gt;
: An exceptional state which the programmer is responsible to deal with&lt;br /&gt;
; User exceptions&lt;br /&gt;
: An exception which can perhaps be solved by the end user of the program, but which may also call for a programmer solution.  User exceptions carries a message for the end user of the program.&lt;br /&gt;
; Definite user errors&lt;br /&gt;
: An exception which is definitely one the end user should deal with, because the programmer cannot do anything about it anyway&lt;br /&gt;
&lt;br /&gt;
You may notice that &amp;quot;error&amp;quot; is used to signal that a person is (believed to be) responsible for the problem, where as &amp;quot;exception&amp;quot; also covers situations with looser relation to specific persons (such as a network failure).&lt;br /&gt;
&lt;br /&gt;
=== Internal errors ===&lt;br /&gt;
&lt;br /&gt;
Internal errors are caused and/or should be prevented by the programmer of the program.&lt;br /&gt;
&lt;br /&gt;
{{Example| A predicate takes two lists as argument and pair the elements of the lists.  So the lists are expected to have the same length.  If the lists have different lengths it is appropriate to raise an &amp;lt;vp&amp;gt;internal_error&amp;lt;/vp&amp;gt;, because it is clearly the responsibility of the programmer to ensure that the lists have same length; the end-user of the program can at most influence this indirectly.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== User exceptions ===&lt;br /&gt;
&lt;br /&gt;
User exceptions typically deal with problems related to external resources such as files, network, databases, web servers, etc.  Often the user will become wiser by being informed about the problem and often the user may even solve the problem.&lt;br /&gt;
&lt;br /&gt;
{{Example|  The read-only file problem discussed above is a typical example of a user exception.  It is the user rather than the programmer that can solve the problem with the read-only file.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
A user exception is distinguished by having extra information in a field with name &amp;lt;vp&amp;gt;common_exception::userMessage_parameter&amp;lt;/vp&amp;gt;.  This extra info should be a message with relevance for an end user of the program.  The message can reference other extra info parameters using the format %PARAM.  The preferred way to raise user exceptions is by means of the predicate &amp;lt;vp&amp;gt;common_exception::raise_user&amp;lt;/vp&amp;gt;.  Likewise you can continue exceptions with a user message using &amp;lt;vp&amp;gt;common_exception::continue_user&amp;lt;/vp&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
{{Example| This predicate will raise a &amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039;user&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039; &amp;lt;vp&amp;gt;fileSystem_api::cannotCreate&amp;lt;/vp&amp;gt; exception &lt;br /&gt;
&lt;br /&gt;
&amp;lt;vip&amp;gt;class predicates&lt;br /&gt;
    raise_cannotCreate : (string Filename) erroneous.&lt;br /&gt;
clauses&lt;br /&gt;
    raise_cannotCreate(Filename) :-&lt;br /&gt;
        common_exception::raise_user(classInfo, fileSystem_api::cannotCreate, predicate_name(),&lt;br /&gt;
            &amp;quot;It is not possible to create the file %Filename&amp;quot;,&lt;br /&gt;
            [namedValue(&amp;quot;Filename&amp;quot;, string(Filename))]).&amp;lt;/vip&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The use of &amp;lt;vp&amp;gt;&amp;quot;%Filename&amp;quot;&amp;lt;/vp&amp;gt; in the message corresponds to the extra info &amp;lt;vp&amp;gt;&amp;quot;Filename&amp;quot;&amp;lt;/vp&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
The predicate &amp;lt;vp&amp;gt;exceptionDump::tryGetUserMessage&amp;lt;/vp&amp;gt; will return a user message from a &amp;lt;vp&amp;gt;traceId&amp;lt;/vp&amp;gt; if possible.  The message will consist of all user messages from the entire trace and will have parameters substituted.&lt;br /&gt;
&lt;br /&gt;
{{Example|  Given &amp;lt;vp&amp;gt;raise_cannotCreate&amp;lt;/vp&amp;gt; from above and calling &amp;lt;vp&amp;gt;test&amp;lt;/vp&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;vip&amp;gt;clauses&lt;br /&gt;
    test() :-&lt;br /&gt;
        try&lt;br /&gt;
            raise_cannotCreate(&amp;quot;test.xxx&amp;quot;)&lt;br /&gt;
         catch TraceId do&lt;br /&gt;
            if UserMsg = exceptionDump::tryGetUserMessage(TraceId) then&lt;br /&gt;
                stdio::write(UserMsg)&lt;br /&gt;
            end if&lt;br /&gt;
         end try.&amp;lt;/vip&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The following message is written to &amp;lt;vp&amp;gt;stdio&amp;lt;/vp&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;text&amp;quot;&amp;gt;It is not possible to create the file test.xxx&amp;lt;/source&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== Definite user errors ===&lt;br /&gt;
&lt;br /&gt;
Definite user errors are exceptions that are solely the responsibility of the user of the program.  For example wrong use of the program.&lt;br /&gt;
&lt;br /&gt;
{{Example| A program can write out some information, but only if the user has specified which information to write.  So if the user invoke the functionality without having specified which information to write, it is appropriate to raise a definite user error.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
A definite user exception is distinguished by adding &amp;lt;vp&amp;gt;true&amp;lt;/vp&amp;gt; as extra info for the parameter &amp;lt;vp&amp;gt;common_exception::definiteUserError_parameter&amp;lt;/vp&amp;gt;.  The preferred way to do this is by using the predicates:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;vp&amp;gt;common_exception::raise_definiteUser&amp;lt;/vp&amp;gt;&lt;br /&gt;
* &amp;lt;vp&amp;gt;common_exception::continue_definiteUser&amp;lt;/vp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The use of these predicates is the same as the user of &amp;lt;vp&amp;gt;common_exception::raise_user&amp;lt;/vp&amp;gt; and &amp;lt;vp&amp;gt;common_exception::continue_user&amp;lt;/vp&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
An exception trace is considered a definite user error if one (or more) entries in the trace carries the &amp;lt;vp&amp;gt;common_exception::definiteUserError_parameter&amp;lt;/vp&amp;gt;.  The predicate &amp;lt;vp&amp;gt;common_exception::isDefiniteUserError&amp;lt;/vp&amp;gt; will succeed for definite user errors.&lt;br /&gt;
&lt;br /&gt;
=== Packed Exceptions ===&lt;br /&gt;
&lt;br /&gt;
Some times, e.g., in a client/server application, you catch an exception on the server which you want to handle on the client. In that case you can serialize the exception on the server send it to the client and reraise it as a packed exception.&lt;br /&gt;
&lt;br /&gt;
On the server&lt;br /&gt;
&amp;lt;vip&amp;gt;&lt;br /&gt;
try&lt;br /&gt;
   ...&lt;br /&gt;
catch E do&lt;br /&gt;
   sendExceptionToClient(exception::getTraceInfo())&lt;br /&gt;
end try,&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/vip&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On the client&lt;br /&gt;
&amp;lt;vip&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
Rtn = remoteCall(...),&lt;br /&gt;
if Rtn = error(ExceptionInfo) then&lt;br /&gt;
    common_exception::raise_packed(ExceptionInfo, classInfo, predicate_name(),&amp;quot;remoteCall returned an exception&amp;quot;)&lt;br /&gt;
end if&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/vip&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The predicate raise_packed works like a continue_unknown but continues a serialized exception instead of normal exception. It is meant to be used when the exception stem from another program and thus only is available in serialized form.&lt;br /&gt;
&lt;br /&gt;
== The error presentation dialog  ==&lt;br /&gt;
&lt;br /&gt;
The error presentation dialog (in the class &amp;lt;vp&amp;gt;errorPresentationDialog&amp;lt;/vp&amp;gt;) is by default used by the default exception handling in a GUI program.  Its behavior is closely related to the classification of exceptions described above, as described by these two rules:&lt;br /&gt;
&lt;br /&gt;
* If the exception trace carries a user message, this message will be presented to the user.&lt;br /&gt;
* If the exception trace is not a definite user error, there will be information for the programmer&lt;br /&gt;
&lt;br /&gt;
So if the exception is an internal error there will only be information for the programmer; if it is a user exception there will both be information for the user and for the programmer; and if it is a user error there will only be information for the user.&lt;br /&gt;
&lt;br /&gt;
If there is information to the programmer the exception dialog will have a details/less details button that can show/hide the programmer information.  It will also have a &amp;quot;report error&amp;quot; button, which by default will copy the information to the clipboard so that the user can easily send it to the programmer.&lt;br /&gt;
&lt;br /&gt;
[[Image:ErrorPresentationDialogDefault.png]]&lt;br /&gt;
&lt;br /&gt;
The dialog is customizable by means of various properties:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;vip&amp;gt;properties&lt;br /&gt;
    title : string. % := &amp;quot;Error&amp;quot;.&lt;br /&gt;
    callBackBtnText : string. % := &amp;quot;&amp;amp;Copy&amp;quot;.&lt;br /&gt;
    dontCallBackBtnText : string. % := &amp;quot;&amp;amp;OK&amp;quot;.&lt;br /&gt;
    showDetailsBtnText : string. % := &amp;quot;Show &amp;amp;Details&amp;quot;.&lt;br /&gt;
    hideDetailsBtnText : string. % := &amp;quot;Hide &amp;amp;Details&amp;quot;.&lt;br /&gt;
    closeApplicationBtnText : string. % := &amp;quot;Close &amp;amp;Application&amp;quot;.&lt;br /&gt;
    commentTextPromt : string. % := &amp;quot;Please describe what you were doing when the error occured:&amp;quot;&lt;br /&gt;
    internalErrorMessage : string. %  := &amp;quot;An internal error has occurred.\nPlease send a bug report to your vendor.&amp;quot;.&lt;br /&gt;
    feedbackMessage : string. %  := &amp;quot;Please send your feedback.&amp;quot;.&lt;br /&gt;
    definiteUserErrorIcon : vpiDomains::resid.&lt;br /&gt;
    userErrorIcon : vpiDomains::resid.&lt;br /&gt;
    internalErrorIcon : vpiDomains::resid.&lt;br /&gt;
    reportErrorDelegate : reportErrorDelegate.&lt;br /&gt;
    extraInfoWriter : writer.&amp;lt;/vip&amp;gt;&lt;br /&gt;
&lt;br /&gt;
All texts and labels are controlled by properties. &lt;br /&gt;
&lt;br /&gt;
The &amp;lt;vp&amp;gt;extraInfoWriter&amp;lt;/vp&amp;gt; is a callback that can be set to include extra info for the programmer.  This information will both be presented in the details window and reported back to the programmer if the user press the &amp;quot;report error&amp;quot; button (i.e. the button which is by default labeled &amp;#039;&amp;#039;&amp;#039;Copy&amp;#039;&amp;#039;&amp;#039;).&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;vp&amp;gt;extraInfoWriter&amp;lt;/vp&amp;gt; callback predicate must have this type:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;vip&amp;gt;domains&lt;br /&gt;
    writer = (outputStream Stream).&amp;lt;/vip&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The dialog will invoke the predicate and then it should simply write extra information to the received stream.&lt;br /&gt;
&lt;br /&gt;
{{Example| The Visual Prolog IDE uses the &amp;lt;vp&amp;gt;extraInfoWriter&amp;lt;/vp&amp;gt; to write version information, information about the open project and information about the last actions carried out in the IDE.  This information will help the programmers to analyze the problem.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
The action performed by the &amp;quot;report error&amp;quot; button is customizable using the property &amp;lt;vp&amp;gt;reportErrorDelegate&amp;lt;/vp&amp;gt;, which is a callback predicate of this type:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;vip&amp;gt;domains&lt;br /&gt;
    reportErrorDelegate = (window Parent, string Comment, optional{exception::traceInfo} TraceInfo, string ExtraInfo).&amp;lt;/vip&amp;gt;&lt;br /&gt;
&lt;br /&gt;
; &amp;lt;vp&amp;gt;Parent&amp;lt;/vp&amp;gt;&lt;br /&gt;
: The error presentation dialog which can be used as parent for additional dialogs.&lt;br /&gt;
; &amp;lt;vp&amp;gt;Comment&amp;lt;/vp&amp;gt;&lt;br /&gt;
: The users comment from the comment box.&lt;br /&gt;
; &amp;lt;vp&amp;gt;TraceInfo&amp;lt;/vp&amp;gt;&lt;br /&gt;
: If the dialog is invoked on an exception the trace info is here, if it is invoked for feedback this value is &amp;lt;vp&amp;gt;none&amp;lt;/vp&amp;gt;&lt;br /&gt;
; &amp;lt;vp&amp;gt;ExtraInfo&amp;lt;/vp&amp;gt;&lt;br /&gt;
: The extra info written by the &amp;lt;vp&amp;gt;extraInfoWriter&amp;lt;/vp&amp;gt; callback&lt;br /&gt;
&lt;br /&gt;
{{Example| In the Visual Prolog IDE the &amp;lt;vp&amp;gt;reportErrorDelegate&amp;lt;/vp&amp;gt; will send the exception information to a WEB service which will insert the notification in a database.  The notifications in the database will then be used to improve the IDE.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
[[Category:Tutorials]]&lt;/div&gt;</summary>
		<author><name>Kehler</name></author>
	</entry>
	<entry>
		<id>https://wiki.visual-prolog.com/index.php?title=Exception_Handling&amp;diff=1660</id>
		<title>Exception Handling</title>
		<link rel="alternate" type="text/html" href="https://wiki.visual-prolog.com/index.php?title=Exception_Handling&amp;diff=1660"/>
		<updated>2008-11-23T12:07:54Z</updated>

		<summary type="html">&lt;p&gt;Kehler: /* The error presentation dialog */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;An exception is a deviation from the expected.  What is an exception in one context may be expected in another context, and thus not an exception in that context.&lt;br /&gt;
&lt;br /&gt;
In Visual Prolog programs exceptions are used to deal with deviations from what is expected in the given context.  When a certain program part gets into a situation it cannot deal with it can &amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039;raise&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039; an exception.  When an exception is raised the program control is transferred to the nearest &amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039;exception handler&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039;.  If the exception handler cannot handle the exception it can either raise a new exception or &amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039;continue&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039; the original exception.&lt;br /&gt;
&lt;br /&gt;
The program will terminate with an error message if there is no exception handler to transfer the control to.&lt;br /&gt;
&lt;br /&gt;
== Introduction to exception handling  ==&lt;br /&gt;
&lt;br /&gt;
There are many concepts and entities to understand when dealing with exceptions.  This section will give an introduction by means of an example.&lt;br /&gt;
&lt;br /&gt;
A certain program needs to write some information to a file.  Therefore it has a predicate &amp;lt;vp&amp;gt;writeInfo&amp;lt;/vp&amp;gt; that can write this information.  &amp;lt;vp&amp;gt;writeInfo&amp;lt;/vp&amp;gt; calls the PFC constructor &amp;lt;vp&amp;gt;outputStream_file::create&amp;lt;/vp&amp;gt; to obtain a stream that it can write the information to:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;vip&amp;gt;clauses&lt;br /&gt;
    writeInfo(Filename) :-&lt;br /&gt;
        S = outputStream_file::create(Filename),&lt;br /&gt;
        …&amp;lt;/vip&amp;gt;&lt;br /&gt;
&lt;br /&gt;
But if the file already exists and is write-protected it is impossible to create the stream.&lt;br /&gt;
&lt;br /&gt;
In &amp;lt;vp&amp;gt;outputStream_file::create&amp;lt;/vp&amp;gt; this situation is considered to be exceptional/unexpected and therefore it raises an exception.&lt;br /&gt;
&lt;br /&gt;
When an exception is raised the program control is transferred to the nearest exception handler, which can hopefully handle the situation and thus bring the program back on track again.&lt;br /&gt;
&lt;br /&gt;
In this case &amp;lt;vp&amp;gt;writeInfo&amp;lt;/vp&amp;gt; is called after the user have entered the file name in a dialog and pressed a &amp;#039;&amp;#039;&amp;#039;Save&amp;#039;&amp;#039;&amp;#039;-button.  So the handling we want is simply to tell the user that the information was not written because the file was write-protected.  The user can choose a different filename, remove the write protection, delete the file, cancel the operation entirely or something else.  But from the program&amp;#039;s point of view the exceptional situation is handled.&lt;br /&gt;
&lt;br /&gt;
To set a handler we use the {{lang2|Terms|try-catch|try-catch}} language construction:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;vip&amp;gt;clauses&lt;br /&gt;
    saveInfo(Filename) :-&lt;br /&gt;
        try&lt;br /&gt;
            writeInfo(Filename)&lt;br /&gt;
         catch TraceId do&lt;br /&gt;
              % &amp;lt;&amp;lt;handle situation&amp;gt;&amp;gt;&lt;br /&gt;
         end try.&amp;lt;/vip&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The code works like this:  &amp;lt;vp&amp;gt;writeInfo&amp;lt;/vp&amp;gt; is called, if it succeeds the {{lang2|Terms|try-catch|try-catch}} construction will not do more and &amp;lt;vp&amp;gt;saveInfo&amp;lt;/vp&amp;gt; will also succeed.&lt;br /&gt;
&lt;br /&gt;
But in the write-protected case &amp;lt;vp&amp;gt;outputStream_file::create&amp;lt;/vp&amp;gt; will raise an exception and therefore the following will take place:&lt;br /&gt;
&lt;br /&gt;
# &amp;lt;vp&amp;gt;TraceId&amp;lt;/vp&amp;gt; will be bound to the (so called) &amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039;trace id&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039;, which is a handle to information about the exception (described in more details below)&lt;br /&gt;
# The handler code (i.e. the code between &amp;lt;vp&amp;gt;do&amp;lt;/vp&amp;gt; and &amp;lt;vp&amp;gt;end try&amp;lt;/vp&amp;gt;) is evaluated&lt;br /&gt;
# The result of the handler code will be the result of the {{lang2|Terms|try-catch|try-catch}} construction, and thus of &amp;lt;vp&amp;gt;saveInfo&amp;lt;/vp&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
So for the &amp;quot;write-protected&amp;quot; exception the handler code should write a message to the user.&lt;br /&gt;
&lt;br /&gt;
If it is another kind of exception the handler will have to do something different.  Especially, it may be an exception that the handler does not know how to handle.  In this case the best thing the handler code can do is to continue the exception as an &amp;#039;&amp;#039;unknown&amp;#039;&amp;#039; exception (i.e. unknown to the handler).&lt;br /&gt;
&lt;br /&gt;
When an exception is continued it consists of the original exception plus some continue information.  If it has been continued by several handlers it will contain a lot of continue information in addition to the original exception information.  The exception information describes a trace from the point of raise through all the handlers.  The &amp;lt;vp&amp;gt;TraceId&amp;lt;/vp&amp;gt; variable that is bound in the {{lang2|Terms|try-catch|try-catch}} construction gives access information about the entire trace (hence the name).&lt;br /&gt;
&lt;br /&gt;
As mentioned above the program will terminate with en error message, if an exception is raised and no handler can be found.  Therefore programs normally setup an outermost default exception handler.  &amp;lt;vp&amp;gt;mainExe::run&amp;lt;/vp&amp;gt; setup such a handler in a console program this is the fall-back handler.  In a GUI program there is also a default hander in the GUI event loop which will catch exceptions arising from the handling of an event.&lt;br /&gt;
&lt;br /&gt;
All in all, the lifecycle of an exception is as follows:&lt;br /&gt;
&lt;br /&gt;
* It is raised&lt;br /&gt;
* It is caught and continued&lt;br /&gt;
* It is caught and continued&lt;br /&gt;
* …&lt;br /&gt;
* It is caught and handled (or the program terminates with an error message)&lt;br /&gt;
&lt;br /&gt;
Each time the exception is caught the trace so far can be examined.  When the exception is raised and each time it is continued extra information can be added to the exception trace.  If nothing else handles an exception it will (normally) be handled by the fallback/default handler of the program.&lt;br /&gt;
&lt;br /&gt;
== Defining an exception ==&lt;br /&gt;
&lt;br /&gt;
An exception is a value of the type &amp;lt;vp&amp;gt;core::exception&amp;lt;/vp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;vip&amp;gt;domains&lt;br /&gt;
    exception = (classInfo ClassInfo [out], string PredicateName [out], string Description [out]).&amp;lt;/vip&amp;gt;&lt;br /&gt;
&lt;br /&gt;
I.e. an exception is a predicate that returns three pieces of information:&lt;br /&gt;
&lt;br /&gt;
; &amp;lt;vp&amp;gt;ClassInfo&amp;lt;/vp&amp;gt;&lt;br /&gt;
: The &amp;lt;vp&amp;gt;classInfo&amp;lt;/vp&amp;gt; of the class that defines the exception&lt;br /&gt;
; &amp;lt;vp&amp;gt;PredicateName&amp;lt;/vp&amp;gt;&lt;br /&gt;
: The name of the exception predicate itself&lt;br /&gt;
; &amp;lt;vp&amp;gt;Description&amp;lt;/vp&amp;gt;&lt;br /&gt;
: A description of the exception&lt;br /&gt;
&lt;br /&gt;
{{example| The &amp;lt;vp&amp;gt;cannotCreate&amp;lt;/vp&amp;gt; exception from the example above is declared in the class &amp;lt;vp&amp;gt;fileSystem_api&amp;lt;/vp&amp;gt; like this:&lt;br /&gt;
&amp;lt;vip&amp;gt;class fileSystem_api&lt;br /&gt;
…&lt;br /&gt;
predicates&lt;br /&gt;
    cannotCreate : exception.&lt;br /&gt;
…&amp;lt;/vip&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The implementation looks like this:&lt;br /&gt;
&amp;lt;vip&amp;gt;impement	 fileSystem_api&lt;br /&gt;
…&lt;br /&gt;
clauses&lt;br /&gt;
    cannotCreate(classInfo, predicate_name(), &amp;quot;Cannot create or open the specified file&amp;quot;).&lt;br /&gt;
…&amp;lt;/vip&amp;gt;&lt;br /&gt;
&amp;lt;vp&amp;gt;classInfo&amp;lt;/vp&amp;gt; is the &amp;lt;vp&amp;gt;classInfo&amp;lt;/vp&amp;gt; of the &amp;lt;vp&amp;gt;fileSystem_api&amp;lt;/vp&amp;gt; class ; &amp;lt;vp&amp;gt;predicate_name&amp;lt;/vp&amp;gt; is a built-in predicate  that returns the name of the predicate in which it is called (i.e. in this case it will return &amp;lt;vp&amp;gt;&amp;quot;cannotCreate&amp;quot;&amp;lt;/vp&amp;gt;).  The last argument is the description of the exception. &lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Many/most programmers will never need to define exceptions, because in many/most cases the exceptions to use are already defined.  An exception definition is only needed when the exception must be distinguished from other kinds of exceptions, such that exception handlers can deal specially with that kind of exception.  Typically exception definitions are only necessary for exceptions that are raised by library software.  I most cases programmers will raise the exception &amp;lt;vp&amp;gt;internal_error&amp;lt;/vp&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Raising an exception ==&lt;br /&gt;
&lt;br /&gt;
Exceptions are raised using the predicate &amp;lt;vp&amp;gt;exception::raise&amp;lt;/vp&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;vip&amp;gt;class exception&lt;br /&gt;
…&lt;br /&gt;
predicates&lt;br /&gt;
    raise : (classInfo ClassInfo, exception Exception) erroneous. &lt;br /&gt;
    raise : (classInfo ClassInfo, exception Exception, namedValue_list ExtraInfo) erroneous.&amp;lt;/vip&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;vp&amp;gt;ClassInfo&amp;lt;/vp&amp;gt;&lt;br /&gt;
: The &amp;lt;vp&amp;gt;classInfo&amp;lt;/vp&amp;gt; of the class that raise the excption&lt;br /&gt;
&amp;lt;vp&amp;gt;Exception&amp;lt;/vp&amp;gt;&lt;br /&gt;
: The exception to raise&lt;br /&gt;
&amp;lt;vp&amp;gt;ExtraInfo&amp;lt;/vp&amp;gt;&lt;br /&gt;
: Extra information about the raised exception.&lt;br /&gt;
&lt;br /&gt;
{{example|The &amp;lt;vp&amp;gt;cannotCreate&amp;lt;/vp&amp;gt; exception from above is raised by the predicate &amp;lt;vp&amp;gt;fileSystem_api::raise_cannotCreate&amp;lt;/vp&amp;gt;. The code  looks like this:&lt;br /&gt;
&amp;lt;vip&amp;gt;clauses&lt;br /&gt;
    raise_cannotCreate(ClassInfo, FileName, LastError) :-&lt;br /&gt;
        Desc = common_exception::getLastErrorDescription(LastError),&lt;br /&gt;
        exception::raise(&lt;br /&gt;
            ClassInfo,&lt;br /&gt;
            cannotCreate,&lt;br /&gt;
            [namedValue(fileSystem_exception::fileName_parameter, string(FileName)),&lt;br /&gt;
             namedValue(common_exception::errorCode_parameter, unsigned(LastError)),&lt;br /&gt;
             namedValue(common_exception::errorDescription_parameter, string(Desc))]).&amp;lt;/vip&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;vp&amp;gt;raise_cannotCreate&amp;lt;/vp&amp;gt; is called with the &amp;lt;vp&amp;gt;ClassInfo&amp;lt;/vp&amp;gt; of the raising class the &amp;lt;vp&amp;gt;FileName&amp;lt;/vp&amp;gt; and the windows error code &amp;lt;vp&amp;gt;LastError&amp;lt;/vp&amp;gt; that the relevant low level Windows API predicate caused.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;vp&amp;gt;common_exception::getLastErrorDescription&amp;lt;/vp&amp;gt; obtains the description corresponding to &amp;lt;vp&amp;gt;LastError&amp;lt;/vp&amp;gt; from Windows.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;vp&amp;gt;exception::raise&amp;lt;/vp&amp;gt; is then used to raise the &amp;lt;vp&amp;gt;cannotCreate&amp;lt;/vp&amp;gt; exception with the three pieces of extra information.   &amp;lt;vp&amp;gt;fileSystem_exception::fileName_parameter&amp;lt;/vp&amp;gt;, &amp;lt;vp&amp;gt;common_exception::errorCode_parameter&amp;lt;/vp&amp;gt; and &amp;lt;vp&amp;gt;common_exception::errorDescription_parameter&amp;lt;/vp&amp;gt; are names (strings) used for the extra information. &lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
It is very common to create helper predicates like  &amp;lt;vp&amp;gt;fileSystem_api::raise_cannotCreate&amp;lt;/vp&amp;gt; to do the actual raising rather that calling &amp;lt;vp&amp;gt;exception::raise&amp;lt;/vp&amp;gt; directly from the code that needs to raise the exception.  That way it is certain that the extra info for this particular exception is handled in the same way in all cases.&lt;br /&gt;
&lt;br /&gt;
Normally the helper raise predicate is created by the same programmer that declares the exception.  And as mentioned above this is normally only programmers that create library software.&lt;br /&gt;
&lt;br /&gt;
Application programmers will in most cases raise exceptions by calling appropriate raiser predicates, typically the ones defined in &amp;lt;vp&amp;gt;common_exception&amp;lt;/vp&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Catching and handling exceptions ==&lt;br /&gt;
&lt;br /&gt;
Exceptions are caught with the {{lang2|Terms|try-catch|try-catch}} construction:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;vipbnf&amp;gt;try &amp;lt;Body&amp;gt; catch &amp;lt;TraceId&amp;gt; do &amp;lt;Handler&amp;gt; end try&amp;lt;/vipbnf&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If &amp;lt;vpbnf&amp;gt;&amp;lt;Body&amp;gt;&amp;lt;/vpbnf&amp;gt; terminates with an exception &amp;lt;vpbnf&amp;gt;&amp;lt;TraceId&amp;gt;&amp;lt;/vpbnf&amp;gt; is bound to the &amp;#039;&amp;#039;trace id&amp;#039;&amp;#039; and then &amp;lt;vpbnf&amp;gt;&amp;lt;Handler&amp;gt;&amp;lt;/vpbnf&amp;gt; is evaluated.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;vpbnf&amp;gt;&amp;lt;TraceId&amp;gt;&amp;lt;/vpbnf&amp;gt; is used to obtain information about the exception trace.  This information can be used for at least two things:&lt;br /&gt;
&lt;br /&gt;
* Determine which kind of exception that is caught, so that it can be decided if and how to handle it&lt;br /&gt;
* Obtain additional information to write to the user, in a log or use for something else&lt;br /&gt;
&lt;br /&gt;
You will call &amp;lt;vp&amp;gt;exception::tryGetDescriptor&amp;lt;/vp&amp;gt; to determine if a certain kind of exception is caught:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;vip&amp;gt;predicates&lt;br /&gt;
    tryGetDescriptor : (traceId TraceID, exception Exception) -&amp;gt; descriptor Descriptor determ.&amp;lt;/vip&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The exception trace corresponding to &amp;lt;vp&amp;gt;TraceId&amp;lt;/vp&amp;gt; is searched for an exception of the kind &amp;lt;vp&amp;gt;Exception&amp;lt;/vp&amp;gt;.  If there is such an entry in the trace (raised or continued) a corresponding exception descriptor is returned in &amp;lt;vp&amp;gt;Descriptor&amp;lt;/vp&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The predicate fails if such an exception is not in the exception trace.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;vp&amp;gt;Descriptor&amp;lt;/vp&amp;gt; contains the extra information about that particular entry in the exception trace:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;vip&amp;gt;domains&lt;br /&gt;
    descriptor = descriptor(classInfoDescriptor ClassInfo, exceptionDescriptor ExceptionInfo, kind Kind,&lt;br /&gt;
        namedValue_list ExtraInfo, gmtTimeValue GMTTime, string ExceptionDescription, unsigned ThreadId).&amp;lt;/vip&amp;gt;&lt;br /&gt;
&lt;br /&gt;
; &amp;lt;vp&amp;gt;ClassInfo&amp;lt;/vp&amp;gt;&lt;br /&gt;
: The &amp;lt;vp&amp;gt;classInfo&amp;lt;/vp&amp;gt; of the class that raised the exception (in functor form)&lt;br /&gt;
; &amp;lt;vp&amp;gt;ExceptionInfo&amp;lt;/vp&amp;gt;&lt;br /&gt;
: The &amp;lt;vp&amp;gt;exception&amp;lt;/vp&amp;gt; in question (in functor form)&lt;br /&gt;
; &amp;lt;vp&amp;gt;Kind&amp;lt;/vp&amp;gt;&lt;br /&gt;
: The entry kind (&amp;lt;vp&amp;gt;raise&amp;lt;/vp&amp;gt; or &amp;lt;vp&amp;gt;continue&amp;lt;/vp&amp;gt;)&lt;br /&gt;
; &amp;lt;vp&amp;gt;ExtraInfo&amp;lt;/vp&amp;gt;&lt;br /&gt;
: The extra information provided with this entry in the trace&lt;br /&gt;
; &amp;lt;vp&amp;gt;GMTTime&amp;lt;/vp&amp;gt;&lt;br /&gt;
: The time this exception trace entry was raised/continued&lt;br /&gt;
; &amp;lt;vp&amp;gt;ExceptionDescription&amp;lt;/vp&amp;gt;&lt;br /&gt;
: The exception description of this entry (this information is also present in &amp;lt;vp&amp;gt;ExceptionInfo&amp;lt;/vp&amp;gt;)&lt;br /&gt;
; &amp;lt;vp&amp;gt;ThreadId&amp;lt;/vp&amp;gt;&lt;br /&gt;
: The thread id of the thread that raised/continued this entry&lt;br /&gt;
&lt;br /&gt;
Much of this information is mainly interesting if the exception is not handled.  The information that is most interesting when handling an exception is:&lt;br /&gt;
&lt;br /&gt;
* The exception kind has been determined to be the one we expected&lt;br /&gt;
* The &amp;lt;vp&amp;gt;ExtraInfo&amp;lt;/vp&amp;gt; for this entry is available for use in messages, etc&lt;br /&gt;
&lt;br /&gt;
The predicate &amp;lt;vp&amp;gt;exception::tryGetExtraInfo&amp;lt;/vp&amp;gt; is convenient for obtaining extra information:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;vip&amp;gt;predicates&lt;br /&gt;
    tryGetExtraInfo : (descriptor Descriptor, string Name) -&amp;gt; value Value determ.&amp;lt;/vip&amp;gt;&lt;br /&gt;
&lt;br /&gt;
; &amp;lt;vp&amp;gt;Descriptor&amp;lt;/vp&amp;gt;&lt;br /&gt;
: Is the description whose extra info we want to get something from.&lt;br /&gt;
; &amp;lt;vp&amp;gt;Name&amp;lt;/vp&amp;gt;&lt;br /&gt;
: The name of the extra info parameter we want to obtain.&lt;br /&gt;
; &amp;lt;vp&amp;gt;Value&amp;lt;/vp&amp;gt;&lt;br /&gt;
: The value that the mentioned parameter has.&lt;br /&gt;
&lt;br /&gt;
{{example|  Code for catching and handling the &amp;lt;vp&amp;gt;fileSystem_api::cannotCreate&amp;lt;/vp&amp;gt; exception can look like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;vip&amp;gt;clauses&lt;br /&gt;
    saveInfo(Filename) :-&lt;br /&gt;
        try&lt;br /&gt;
            writeInfo(Filename)&lt;br /&gt;
         catch TraceId do&lt;br /&gt;
              if D = exception::tryGetDescriptor(TraceId, fileSystem_api::cannotCreate) then&lt;br /&gt;
                stdio::write(&amp;quot;Cannot write to the file: &amp;quot;, Filename),&lt;br /&gt;
                if string(Description) = exception::tryGetExtraInfo(D, common_exception::errorDescription_parameter) then&lt;br /&gt;
                    stdio::writef(&amp;quot;; %&amp;quot;, Description)&lt;br /&gt;
                end if,&lt;br /&gt;
                stdio::write(&amp;quot;\n&amp;quot;)&lt;br /&gt;
            else&lt;br /&gt;
                common_exception::continue_unknown(TraceId, classInfo, predicate_name(), &amp;quot;Filename = &amp;quot;, Filename)&lt;br /&gt;
            end if&lt;br /&gt;
         end try.&amp;lt;/vip&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The code here don&amp;#039;t need to obtain the &amp;lt;vp&amp;gt;fileSystem_exception::fileName_parameter&amp;lt;/vp&amp;gt;, because the file name is already known in the &amp;lt;vp&amp;gt;Filename&amp;lt;/vp&amp;gt; variable.&lt;br /&gt;
&lt;br /&gt;
But we can obtain Window&amp;#039;s description of the problem querying for &amp;lt;vp&amp;gt;common_exception::errorDescription_parameter&amp;lt;/vp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We &amp;#039;&amp;#039;&amp;#039;continue&amp;#039;&amp;#039;&amp;#039; the exception as unknown if it is not the &amp;lt;vp&amp;gt;cannotCreate&amp;lt;/vp&amp;gt; kind .  For the continue call we add the filename as.  &amp;lt;vp&amp;gt;common_exception::continue_unknown&amp;lt;/vp&amp;gt; will create a string of the extra arguments and add it as an &amp;lt;vp&amp;gt;common_exception::errorArguments_parameter&amp;lt;/vp&amp;gt;.  Such information is mainly for use in the default exception handler to be discussed below. &lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== Serializing exceptions ==&lt;br /&gt;
&lt;br /&gt;
In some situations the best way to handle  an exception is by sending all the information about the exception somewhere else.  A server might for example want to send the information to the client program that caused the exception, because then there is a user that can take action.&lt;br /&gt;
&lt;br /&gt;
A &amp;lt;vp&amp;gt;traceId&amp;lt;/vp&amp;gt; only have a meaning in the process that has created it, but the predicate &amp;lt;vp&amp;gt;exception::getTraceInfo&amp;lt;/vp&amp;gt; can create a &amp;lt;vp&amp;gt;traceInfo&amp;lt;/vp&amp;gt; structure (&amp;lt;vp&amp;gt;TraceInfo&amp;lt;/vp&amp;gt;) from the &amp;lt;vp&amp;gt;traceId TraceId&amp;lt;/vp&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;vip&amp;gt;predicates&lt;br /&gt;
    getTraceInfo : (traceId TraceId) -&amp;gt; traceInfo TraceInfo.&amp;lt;/vip&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Such a structure is a functor structure that can be serialized/deserialized with &amp;lt;vp&amp;gt;toString&amp;lt;/vp&amp;gt;/&amp;lt;vp&amp;gt;toTerm&amp;lt;/vp&amp;gt;; &amp;lt;vp&amp;gt;write&amp;lt;/vp&amp;gt;/&amp;lt;vp&amp;gt;read&amp;lt;/vp&amp;gt;; nested in a fact database using &amp;lt;vp&amp;gt;save&amp;lt;/vp&amp;gt;/&amp;lt;vp&amp;gt;consult&amp;lt;/vp&amp;gt;; etc.&lt;br /&gt;
&lt;br /&gt;
== Exception dumps ==&lt;br /&gt;
&lt;br /&gt;
The class &amp;lt;vp&amp;gt;exceptionDump&amp;lt;/vp&amp;gt; contains predicates for dumping exception traces to &amp;lt;vp&amp;gt;stdio&amp;lt;/vp&amp;gt;, some other &amp;lt;vp&amp;gt;outputStream&amp;lt;/vp&amp;gt; or a &amp;lt;vp&amp;gt;string&amp;lt;/vp&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
An exception dump contains three major pieces of information:&lt;br /&gt;
&lt;br /&gt;
* A dump of the call stack (with file names and line numbers) from the point where the exception was raised&lt;br /&gt;
* A dump of the exception-trace with all the information from the exception descriptors&lt;br /&gt;
* Information about the operating system that the program ran on&lt;br /&gt;
 &lt;br /&gt;
&amp;lt;vp&amp;gt;exceptionDump&amp;lt;/vp&amp;gt; have predicates both for dumping exception traces both from a &amp;lt;vp&amp;gt;traceId&amp;lt;/vp&amp;gt; and from a &amp;lt;vp&amp;gt;traceInfo&amp;lt;/vp&amp;gt; obtained with &amp;lt;vp&amp;gt;exception::getTraceInfo&amp;lt;/vp&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Dumps for a certain program are in general only useful to the programmers of that program; the users of the program will find dumps cryptic and rather uninteresting.  I.e. the purpose of dumps is to give the programmer means for improving the program.&lt;br /&gt;
&lt;br /&gt;
== Default handling ==&lt;br /&gt;
&lt;br /&gt;
A program should handle all exceptions, because if an exception is continued or raised at a point where there is no handler the program will terminate with a rather bad error message.  The error message is bad because most exception handling is done in PFC; the language itself knows nothing about exception traces and the like.&lt;br /&gt;
&lt;br /&gt;
To be sure that all exceptions are handled it is normal to set up a default (or fallback) exception handler.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;vp&amp;gt;mainExe::run&amp;lt;/vp&amp;gt; (and &amp;lt;vp&amp;gt;mainExe::runCom&amp;lt;/vp&amp;gt;) which is normally called in the goal setup such a default exception handler: It runs the &amp;lt;vp&amp;gt;main::run&amp;lt;/vp&amp;gt; predicate inside a {{lang2|Terms|try-catch|try-catch}} construction that will handle any exception.&lt;br /&gt;
&lt;br /&gt;
The handler in &amp;lt;vp&amp;gt;mainExe::run&amp;lt;/vp&amp;gt; (and &amp;lt;vp&amp;gt;mainExe::runCom&amp;lt;/vp&amp;gt;) dumps the entire exception trace to output stream in &amp;lt;vp&amp;gt;stdio&amp;lt;/vp&amp;gt;.  And then the program will terminate.  The idea is that:&lt;br /&gt;
&lt;br /&gt;
* Perhaps the user can see something from the dump (which may for example say that &amp;#039;&amp;#039;access is denied&amp;#039;&amp;#039; to &amp;#039;&amp;#039;xxx.txt&amp;#039;&amp;#039;)&lt;br /&gt;
* Alternatively, the developer of the program may use the dump to improve the program&lt;br /&gt;
&lt;br /&gt;
In addition to the handler in &amp;lt;vp&amp;gt;mainExe::run&amp;lt;/vp&amp;gt; a GUI program also set a default handler in the event loop.  This handler is set by calling &amp;lt;vp&amp;gt;applicationWindow::setErrorResponder&amp;lt;/vp&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;vip&amp;gt;domains&lt;br /&gt;
    errorResponder = (applicationWindow Source, exception::traceId TraceId).&lt;br /&gt;
&lt;br /&gt;
predicates&lt;br /&gt;
    setErrorResponder : (errorResponder Responder).&amp;lt;/vip&amp;gt;&lt;br /&gt;
&lt;br /&gt;
By default the error responder &amp;lt;vp&amp;gt;errorPresentationDialog::present&amp;lt;/vp&amp;gt; is used.  The functioning of the &amp;lt;pv&amp;gt;errorPresentationDialog&amp;lt;/vp&amp;gt; is closely related to a categorization of exceptions described in the next section.&lt;br /&gt;
&lt;br /&gt;
PFC place exceptions in three major categories based on who is (believed to be) responsible:&lt;br /&gt;
&lt;br /&gt;
; Internal errors&lt;br /&gt;
: An exceptional state which the programmer is responsible to deal with&lt;br /&gt;
; User exceptions&lt;br /&gt;
: An exception which can perhaps be solved by the end user of the program, but which may also call for a programmer solution.  User exceptions carries a message for the end user of the program.&lt;br /&gt;
; Definite user errors&lt;br /&gt;
: An exception which is definitely one the end user should deal with, because the programmer cannot do anything about it anyway&lt;br /&gt;
&lt;br /&gt;
You may notice that &amp;quot;error&amp;quot; is used to signal that a person is (believed to be) responsible for the problem, where as &amp;quot;exception&amp;quot; also covers situations with looser relation to specific persons (such as a network failure).&lt;br /&gt;
&lt;br /&gt;
=== Internal errors ===&lt;br /&gt;
&lt;br /&gt;
Internal errors are caused and/or should be prevented by the programmer of the program.&lt;br /&gt;
&lt;br /&gt;
{{Example| A predicate takes two lists as argument and pair the elements of the lists.  So the lists are expected to have the same length.  If the lists have different lengths it is appropriate to raise an &amp;lt;vp&amp;gt;internal_error&amp;lt;/vp&amp;gt;, because it is clearly the responsibility of the programmer to ensure that the lists have same length; the end-user of the program can at most influence this indirectly.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== User exceptions ===&lt;br /&gt;
&lt;br /&gt;
User exceptions typically deal with problems related to external resources such as files, network, databases, web servers, etc.  Often the user will become wiser by being informed about the problem and often the user may even solve the problem.&lt;br /&gt;
&lt;br /&gt;
{{Example|  The read-only file problem discussed above is a typical example of a user exception.  It is the user rather than the programmer that can solve the problem with the read-only file.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
A user exception is distinguished by having extra information in a field with name &amp;lt;vp&amp;gt;common_exception::userMessage_parameter&amp;lt;/vp&amp;gt;.  This extra info should be a message with relevance for an end user of the program.  The message can reference other extra info parameters using the format %PARAM.  The preferred way to raise user exceptions is by means of the predicate &amp;lt;vp&amp;gt;common_exception::raise_user&amp;lt;/vp&amp;gt;.  Likewise you can continue exceptions with a user message using &amp;lt;vp&amp;gt;common_exception::continue_user&amp;lt;/vp&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
{{Example| This predicate will raise a &amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039;user&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039; &amp;lt;vp&amp;gt;fileSystem_api::cannotCreate&amp;lt;/vp&amp;gt; exception &lt;br /&gt;
&lt;br /&gt;
&amp;lt;vip&amp;gt;class predicates&lt;br /&gt;
    raise_cannotCreate : (string Filename) erroneous.&lt;br /&gt;
clauses&lt;br /&gt;
    raise_cannotCreate(Filename) :-&lt;br /&gt;
        common_exception::raise_user(classInfo, fileSystem_api::cannotCreate, predicate_name(),&lt;br /&gt;
            &amp;quot;It is not possible to create the file %Filename&amp;quot;,&lt;br /&gt;
            [namedValue(&amp;quot;Filename&amp;quot;, string(Filename))]).&amp;lt;/vip&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The use of &amp;lt;vp&amp;gt;&amp;quot;%Filename&amp;quot;&amp;lt;/vp&amp;gt; in the message corresponds to the extra info &amp;lt;vp&amp;gt;&amp;quot;Filename&amp;quot;&amp;lt;/vp&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
The predicate &amp;lt;vp&amp;gt;exceptionDump::tryGetUserMessage&amp;lt;/vp&amp;gt; will return a user message from a &amp;lt;vp&amp;gt;traceId&amp;lt;/vp&amp;gt; if possible.  The message will consist of all user messages from the entire trace and will have parameters substituted.&lt;br /&gt;
&lt;br /&gt;
{{Example|  Given &amp;lt;vp&amp;gt;raise_cannotCreate&amp;lt;/vp&amp;gt; from above and calling &amp;lt;vp&amp;gt;test&amp;lt;/vp&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;vip&amp;gt;clauses&lt;br /&gt;
    test() :-&lt;br /&gt;
        try&lt;br /&gt;
            raise_cannotCreate(&amp;quot;test.xxx&amp;quot;)&lt;br /&gt;
         catch TraceId do&lt;br /&gt;
            if UserMsg = exceptionDump::tryGetUserMessage(TraceId) then&lt;br /&gt;
                stdio::write(UserMsg)&lt;br /&gt;
            end if&lt;br /&gt;
         end try.&amp;lt;/vip&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The following message is written to &amp;lt;vp&amp;gt;stdio&amp;lt;/vp&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;text&amp;quot;&amp;gt;It is not possible to create the file test.xxx&amp;lt;/source&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== Definite user errors ===&lt;br /&gt;
&lt;br /&gt;
Definite user errors are exceptions that are solely the responsibility of the user of the program.  For example wrong use of the program.&lt;br /&gt;
&lt;br /&gt;
{{Example| A program can write out some information, but only if the user has specified which information to write.  So if the user invoke the functionality without having specified which information to write, it is appropriate to raise a definite user error.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
A definite user exception is distinguished by adding &amp;lt;vp&amp;gt;true&amp;lt;/vp&amp;gt; as extra info for the parameter &amp;lt;vp&amp;gt;common_exception::definiteUserError_parameter&amp;lt;/vp&amp;gt;.  The preferred way to do this is by using the predicates:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;vp&amp;gt;common_exception::raise_definiteUser&amp;lt;/vp&amp;gt;&lt;br /&gt;
* &amp;lt;vp&amp;gt;common_exception::continue_definiteUser&amp;lt;/vp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The use of these predicates is the same as the user of &amp;lt;vp&amp;gt;common_exception::raise_user&amp;lt;/vp&amp;gt; and &amp;lt;vp&amp;gt;common_exception::continue_user&amp;lt;/vp&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
An exception trace is considered a definite user error if one (or more) entries in the trace carries the &amp;lt;vp&amp;gt;common_exception::definiteUserError_parameter&amp;lt;/vp&amp;gt;.  The predicate &amp;lt;vp&amp;gt;common_exception::isDefiniteUserError&amp;lt;/vp&amp;gt; will succeed for definite user errors.&lt;br /&gt;
&lt;br /&gt;
=== Packed Exceptions ===&lt;br /&gt;
&lt;br /&gt;
Some times, e.g., in a client/server application, you catch an exception on the server which you want to handle on the client. In that case you can serialize the exception on the server send it to the client and reraise it as a packed exception.&lt;br /&gt;
&lt;br /&gt;
On the server&lt;br /&gt;
&amp;lt;vip&amp;gt;&lt;br /&gt;
try&lt;br /&gt;
   ...&lt;br /&gt;
catch E do&lt;br /&gt;
   sendExceptionToClient(exception::getTraceInfo())&lt;br /&gt;
end try,&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/vip&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On the client&lt;br /&gt;
&amp;lt;vip&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
Rtn = remoteCall(...),&lt;br /&gt;
if Rtn = error(ExceptionInfo) then&lt;br /&gt;
    common_exception::raise_packed(ExceptionInfo, classInfo, predicate_name(),&amp;quot;remoteCall returned an exception&amp;quot;)&lt;br /&gt;
end if&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/vip&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== The error presentation dialog  ==&lt;br /&gt;
&lt;br /&gt;
The error presentation dialog (in the class &amp;lt;vp&amp;gt;errorPresentationDialog&amp;lt;/vp&amp;gt;) is by default used by the default exception handling in a GUI program.  Its behavior is closely related to the classification of exceptions described above, as described by these two rules:&lt;br /&gt;
&lt;br /&gt;
* If the exception trace carries a user message, this message will be presented to the user.&lt;br /&gt;
* If the exception trace is not a definite user error, there will be information for the programmer&lt;br /&gt;
&lt;br /&gt;
So if the exception is an internal error there will only be information for the programmer; if it is a user exception there will both be information for the user and for the programmer; and if it is a user error there will only be information for the user.&lt;br /&gt;
&lt;br /&gt;
If there is information to the programmer the exception dialog will have a details/less details button that can show/hide the programmer information.  It will also have a &amp;quot;report error&amp;quot; button, which by default will copy the information to the clipboard so that the user can easily send it to the programmer.&lt;br /&gt;
&lt;br /&gt;
[[Image:ErrorPresentationDialogDefault.png]]&lt;br /&gt;
&lt;br /&gt;
The dialog is customizable by means of various properties:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;vip&amp;gt;properties&lt;br /&gt;
    title : string. % := &amp;quot;Error&amp;quot;.&lt;br /&gt;
    callBackBtnText : string. % := &amp;quot;&amp;amp;Copy&amp;quot;.&lt;br /&gt;
    dontCallBackBtnText : string. % := &amp;quot;&amp;amp;OK&amp;quot;.&lt;br /&gt;
    showDetailsBtnText : string. % := &amp;quot;Show &amp;amp;Details&amp;quot;.&lt;br /&gt;
    hideDetailsBtnText : string. % := &amp;quot;Hide &amp;amp;Details&amp;quot;.&lt;br /&gt;
    closeApplicationBtnText : string. % := &amp;quot;Close &amp;amp;Application&amp;quot;.&lt;br /&gt;
    commentTextPromt : string. % := &amp;quot;Please describe what you were doing when the error occured:&amp;quot;&lt;br /&gt;
    internalErrorMessage : string. %  := &amp;quot;An internal error has occurred.\nPlease send a bug report to your vendor.&amp;quot;.&lt;br /&gt;
    feedbackMessage : string. %  := &amp;quot;Please send your feedback.&amp;quot;.&lt;br /&gt;
    definiteUserErrorIcon : vpiDomains::resid.&lt;br /&gt;
    userErrorIcon : vpiDomains::resid.&lt;br /&gt;
    internalErrorIcon : vpiDomains::resid.&lt;br /&gt;
    reportErrorDelegate : reportErrorDelegate.&lt;br /&gt;
    extraInfoWriter : writer.&amp;lt;/vip&amp;gt;&lt;br /&gt;
&lt;br /&gt;
All texts and labels are controlled by properties. &lt;br /&gt;
&lt;br /&gt;
The &amp;lt;vp&amp;gt;extraInfoWriter&amp;lt;/vp&amp;gt; is a callback that can be set to include extra info for the programmer.  This information will both be presented in the details window and reported back to the programmer if the user press the &amp;quot;report error&amp;quot; button (i.e. the button which is by default labeled &amp;#039;&amp;#039;&amp;#039;Copy&amp;#039;&amp;#039;&amp;#039;).&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;vp&amp;gt;extraInfoWriter&amp;lt;/vp&amp;gt; callback predicate must have this type:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;vip&amp;gt;domains&lt;br /&gt;
    writer = (outputStream Stream).&amp;lt;/vip&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The dialog will invoke the predicate and then it should simply write extra information to the received stream.&lt;br /&gt;
&lt;br /&gt;
{{Example| The Visual Prolog IDE uses the &amp;lt;vp&amp;gt;extraInfoWriter&amp;lt;/vp&amp;gt; to write version information, information about the open project and information about the last actions carried out in the IDE.  This information will help the programmers to analyze the problem.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
The action performed by the &amp;quot;report error&amp;quot; button is customizable using the property &amp;lt;vp&amp;gt;reportErrorDelegate&amp;lt;/vp&amp;gt;, which is a callback predicate of this type:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;vip&amp;gt;domains&lt;br /&gt;
    reportErrorDelegate = (window Parent, string Comment, optional{exception::traceInfo} TraceInfo, string ExtraInfo).&amp;lt;/vip&amp;gt;&lt;br /&gt;
&lt;br /&gt;
; &amp;lt;vp&amp;gt;Parent&amp;lt;/vp&amp;gt;&lt;br /&gt;
: The error presentation dialog which can be used as parent for additional dialogs.&lt;br /&gt;
; &amp;lt;vp&amp;gt;Comment&amp;lt;/vp&amp;gt;&lt;br /&gt;
: The users comment from the comment box.&lt;br /&gt;
; &amp;lt;vp&amp;gt;TraceInfo&amp;lt;/vp&amp;gt;&lt;br /&gt;
: If the dialog is invoked on an exception the trace info is here, if it is invoked for feedback this value is &amp;lt;vp&amp;gt;none&amp;lt;/vp&amp;gt;&lt;br /&gt;
; &amp;lt;vp&amp;gt;ExtraInfo&amp;lt;/vp&amp;gt;&lt;br /&gt;
: The extra info written by the &amp;lt;vp&amp;gt;extraInfoWriter&amp;lt;/vp&amp;gt; callback&lt;br /&gt;
&lt;br /&gt;
{{Example| In the Visual Prolog IDE the &amp;lt;vp&amp;gt;reportErrorDelegate&amp;lt;/vp&amp;gt; will send the exception information to a WEB service which will insert the notification in a database.  The notifications in the database will then be used to improve the IDE.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
[[Category:Tutorials]]&lt;/div&gt;</summary>
		<author><name>Kehler</name></author>
	</entry>
	<entry>
		<id>https://wiki.visual-prolog.com/index.php?title=Main_Page&amp;diff=280</id>
		<title>Main Page</title>
		<link rel="alternate" type="text/html" href="https://wiki.visual-prolog.com/index.php?title=Main_Page&amp;diff=280"/>
		<updated>2007-09-05T13:00:52Z</updated>

		<summary type="html">&lt;p&gt;Kehler: Protected &amp;quot;Main Page&amp;quot;: pdc&amp;#039;s [edit=sysop:move=sysop]&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Welcome to the Visual Prolog wiki==&lt;br /&gt;
&lt;br /&gt;
This wiki is dedicated to [http://www.visual-prolog.com/ Visual Prolog] and related tools and libraries.&lt;br /&gt;
&lt;br /&gt;
We are proud that so many enthusiastic users put such a great effort into Visual Prolog.  We hope and trust that this wiki will serve as a significant platform for knowledge exchange in the community.&lt;br /&gt;
&lt;br /&gt;
===Prolog Development Center===&lt;br /&gt;
&lt;br /&gt;
[http://www.pdc.dk/ Prolog Development Center] (PDC) is the company behind Visual Prolog. &lt;br /&gt;
&lt;br /&gt;
PDC will contribute where it can, but the real value of the wiki comes from your contributions. PDC will also monitor the wiki for SPAM and other malicious use, but not otherwise control the contents of the wiki.&lt;br /&gt;
&lt;br /&gt;
===Contribution===&lt;br /&gt;
&lt;br /&gt;
To contribute to this wiki you must register yourself and have your email address validated (see [[wiki.visual-prolog.com:Privacy_policy|Privacy Policy]]).  You are encouraged to provide your real life name as user name.&lt;br /&gt;
&lt;br /&gt;
===Wiki software and help===&lt;br /&gt;
&lt;br /&gt;
The wiki is based on [http://www.mediawiki.org/wiki/MediaWiki MediaWiki] software, which is also used for [http://www.wikipedia.org/ Wikipedia].  If you seek help about the wiki itself and cannot find it here, you may search in [http://www.mediawiki.org/wiki/Help:Contents MediaWiki help pages] and [http://en.wikipedia.org/wiki/Help:Contents Wikipedea help pages].&lt;br /&gt;
&lt;br /&gt;
==Contents==&lt;br /&gt;
&lt;br /&gt;
Currently the main contains is a number of Visual Prolog [[:Category:Tutorials|Tutorials]].&lt;br /&gt;
&lt;br /&gt;
==See Also==&lt;br /&gt;
&lt;br /&gt;
* Visual Prolog [http://www.visual-prolog.com homepage]&lt;br /&gt;
* Visual Prolog [http://discuss.visual-prolog.com discussion forum]&lt;br /&gt;
* [http://www.pdc.dk/ Prolog Development Center]&lt;br /&gt;
&lt;br /&gt;
__NOTOC__ __NOEDITSECTION__&lt;/div&gt;</summary>
		<author><name>Kehler</name></author>
	</entry>
	<entry>
		<id>https://wiki.visual-prolog.com/index.php?title=Main_Page&amp;diff=275</id>
		<title>Main Page</title>
		<link rel="alternate" type="text/html" href="https://wiki.visual-prolog.com/index.php?title=Main_Page&amp;diff=275"/>
		<updated>2007-09-04T15:50:35Z</updated>

		<summary type="html">&lt;p&gt;Kehler: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Welcome to the Visual Prolog wiki==&lt;br /&gt;
&lt;br /&gt;
This wiki is dedicated to [http://www.visual-prolog.com/ Visual Prolog] and related tools and libraries.&lt;br /&gt;
&lt;br /&gt;
We are proud that so many enthusiastic users put such a great effort into Visual Prolog.  We hope and trust that this wiki will serve as a significant platform for knowledge exchange in the community.&lt;br /&gt;
&lt;br /&gt;
===Prolog Development Center===&lt;br /&gt;
&lt;br /&gt;
[http://www.pdc.dk/ Prolog Development Center] (PDC) is the company behind Visual Prolog. &lt;br /&gt;
&lt;br /&gt;
PDC will contribute where it can, but the real value of the wiki comes from your contributions. PDC will also monitor the wiki for SPAM and other malicious use, but not otherwise control the contents of the wiki.&lt;br /&gt;
&lt;br /&gt;
===Contribution===&lt;br /&gt;
&lt;br /&gt;
To contribute to this wiki you must register yourself and have your email address validated (see [[wiki.visual-prolog.com:Privacy_policy|Privacy Policy]]).  You are encouraged to provide your real life name as user name.&lt;br /&gt;
&lt;br /&gt;
===Wiki software and help===&lt;br /&gt;
&lt;br /&gt;
The wiki is based on [http://www.mediawiki.org/wiki/MediaWiki MediaWiki] software, which is also used for [http://www.wikipedia.org/ Wikipedia].  If you seek help about the wiki itself and cannot find it here, you may search in [http://www.mediawiki.org/wiki/Help:Contents MediaWiki help pages] and [http://en.wikipedia.org/wiki/Help:Contents Wikipedea help pages].&lt;br /&gt;
&lt;br /&gt;
==Contents==&lt;br /&gt;
&lt;br /&gt;
Currently the main contains is a number of Visual Prolog [[:Category:Tutorials|Tutorials]].&lt;br /&gt;
&lt;br /&gt;
==See Also==&lt;br /&gt;
&lt;br /&gt;
* Visual Prolog [http://www.visual-prolog.com homepage]&lt;br /&gt;
* Visual Prolog [http://discuss.visual-prolog.com discussion forum]&lt;br /&gt;
* [http://www.pdc.dk/ Prolog Development Center]&lt;br /&gt;
&lt;br /&gt;
__NOTOC__ __NOEDITSECTION__&lt;/div&gt;</summary>
		<author><name>Kehler</name></author>
	</entry>
	<entry>
		<id>https://wiki.visual-prolog.com/index.php?title=Main_Page&amp;diff=18</id>
		<title>Main Page</title>
		<link rel="alternate" type="text/html" href="https://wiki.visual-prolog.com/index.php?title=Main_Page&amp;diff=18"/>
		<updated>2007-07-17T07:48:32Z</updated>

		<summary type="html">&lt;p&gt;Kehler: /* Visual Prolog Token Coloring */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This is the Visual Prolog Wiki.  Currently, this is only for test puposes.  There is still many configurations that need to be done.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Notice&amp;#039;&amp;#039;&amp;#039;: The underlying database is &amp;#039;&amp;#039;&amp;#039;not yet backed-up&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
&lt;br /&gt;
The Wiki is based on MediaWiki software (IIS+PHP+MySQL).&lt;br /&gt;
&lt;br /&gt;
=== Visual Prolog Token Coloring ===&lt;br /&gt;
&lt;br /&gt;
The Wiki has a special Visual Prolog extension.  If you write:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&amp;lt;vip&amp;gt;&amp;lt;/nowiki&amp;gt;some Visual Prolog code&amp;lt;/vip&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The code will be token colered according to Visual Prolog rules (more or less).  For example:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&amp;lt;vip&amp;gt;predicates&lt;br /&gt;
     isMember : (Elem Value, Elem* List) determ.&lt;br /&gt;
     %@short Succeds is #Value is member of #List.&lt;br /&gt;
     %@end&lt;br /&gt;
 clauses&lt;br /&gt;
     isMember(V, [V|_L]) :- !.&lt;br /&gt;
     isMember(V, [_X|L]) :- isMember(V, L).&amp;lt;/vip&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The result will look like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;vip&amp;gt;predicates&lt;br /&gt;
    isMember : (Elem Value, Elem* List) determ.&lt;br /&gt;
    %@short Succeds is #Value is member of #List.&lt;br /&gt;
    %@end&lt;br /&gt;
clauses&lt;br /&gt;
    isMember(V, [V|_L]) :- !.&lt;br /&gt;
    isMember(V, [_X|L]) :- isMember(V, L).&amp;lt;/vip&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Tutorials ==&lt;br /&gt;
&lt;br /&gt;
[[Fundamental Prolog Part 1]]&lt;br /&gt;
&lt;br /&gt;
== Media Wiki Getting started ==&lt;br /&gt;
&lt;br /&gt;
Consult the [http://meta.wikimedia.org/wiki/Help:Contents User&amp;#039;s Guide] for information on using the wiki software.&lt;br /&gt;
&lt;br /&gt;
* [http://www.mediawiki.org/wiki/Help:Configuration_settings Configuration settings list]&lt;br /&gt;
* [http://www.mediawiki.org/wiki/Help:FAQ MediaWiki FAQ]&lt;br /&gt;
* [http://mail.wikimedia.org/mailman/listinfo/mediawiki-announce MediaWiki release mailing list]&lt;/div&gt;</summary>
		<author><name>Kehler</name></author>
	</entry>
</feed>