Обработка исключений: различия между версиями

Материал из wikiru.visual-prolog.com

м
 
(не показаны 24 промежуточные версии 2 участников)
Строка 1: Строка 1:
An exception is a deviation of a program from its "normal" execution path. The PFC exception package contains predicates to catch exceptions, which occur in a prolog program. This tutorial describes:
Исключение - это отклонение программы от маршрута "нормального" выполнения. Пакет exception из состава PFC содержит предикаты помогающие обрабатывать и распространять исключения, которые возникают в программах на Прологе. Это руководство объясняет:


*How to handle exceptions;
*Как обрабатывать исключения;
*Как возбуждать ваши собственные исключения;
*Как продолжать другое исключение.


*How to raise your own exception;
==Как перехватывать исключения==


*How to continue another exception.
Рассмотрим программу, которая читает текстовый файл и выводит его содержимое на консоль. PFC предлагает предикат '''file::readString''', который позволяет выполнить эту задачу. Однако, некоторые обстоятельства могут помешать эту задачу; например, заданное имя файла ссылается на несуществующий файл. Когда предикат '''file::readString''' не может выполнить задачу, он генерирует исключение.


==How to Catch Exceptions==
Visual Prolog предлагает конструкцию '''try/catch''' (см. [[#trap vs try|Try вместо Trap]]), которая перехватывает исключение и позволяет его обработать. Детальное описание этой конструкции можно найти в справке по Visual Prolog ('''Language Reference -> Exception Handling''').


Let us consider a program that reads a text file and prints its content to the console. The PFC supply the '''file::readString'''  predicate that can fulfill the task. However, some cases can prevent to implement the task; for example, a specified file name can point to a non-existing file. When predicate '''file::readString''' cannot fulfill the task, it generates an exception.
Соответственно, код для перехвата исключения будет выглядеть так:
<vip>try 
    MyTxtFileContent = file::readString(myFileName, _IsUnicode)
catch ErrorCode do
    handleFileReadError(ErrorCode)
end try,
...</vip>


Visual Prolog supplies a built-in '''trap/3'''  predicate to catch an exception and process it. Please, see Visual Prolog online Help ('''Language Reference -> Built-in Domains, Predicates and Constants-> Predicates ->trap topic''') for more details about the '''trap/3''' predicate.
Самое интересное здесь это - имплементация предиката handleFileReadError:
 
Therefore the code to catch an exception will look like:
 
<vip>trap(MyTxtFileContent = file::readString(myFileName, _IsUnicode),
    ErrorCode, handleFileReadError(ErrorCode)),</vip>
 
The most interesting part is the implementation of the handleFileReadError predicate:


<vip>class predicates
<vip>class predicates
     handleFileReadError : ( exception::traceID TraceId ) failure.
     handleFileReadError : (exception::traceID TraceId) failure.
clauses
clauses
     handleFileReadError(TraceId):-
     handleFileReadError(TraceId):-
         Descriptor = exception::tryGetDescriptor(TraceId, fileSystem_api::cannotcreate),
         Descriptor = exception::tryGetDescriptor(TraceId, fileSystem_api::cannotcreate),
         !, % file cannot be loaded
         !, % файл не может быт загружен
         exception::descriptor(_ErrorCode, % ErrorCode is used if user invoked errorExit himself.
         exception::descriptor(_ErrorCode, % ErrorCode используется, если пользователь сам вызывает errorExit.
             _ClassInfo, % class information of the class, which raised the exception .
             _ClassInfo, % информация о классе, который возбудил исключение.
             _Exception, % actually it is fileSystem_api::cannotcreate,
             _Exception, % на самом деле это fileSystem_api::cannotcreate,
             % but the parameter should not be compared by ' = ' .
             % но параметр не может участвовать в сравнении с помощью ' = '.
             % See exceptionState::equals
             % смотрите exceptionState::equals
             _Kind, % exception can be raised or continued
             _Kind, % исключение может быть возбуждено или продолжено
             ExtraInfo,
             ExtraInfo,
             _TraceId, % here is the TraceId, but it is not necessary to check once more
             _TraceId, % здесь идентификатор ошибки, но необходимости в проверке нет
             _GMTTime, % the time of exception creation .
             _GMTTime, % время возникновения исключения
             ExceptionDescription,
             ExceptionDescription,
             _ThreadId) = Descriptor,
             _ThreadId) = Descriptor,
Строка 41: Строка 42:
         Reason = namedValue::mapLookUp(ExtraInfo,
         Reason = namedValue::mapLookUp(ExtraInfo,
         common_exception::errorDescription_parameter, string("")),
         common_exception::errorDescription_parameter, string("")),
         stdIO::write("Cannot load file due to: ",ExceptionDescription,
         stdIO::write("Невозможно загрузить файл по причине: ",ExceptionDescription,
             "\nFileName: ", FileName,
             "\nИмя файла: ", FileName,
             "\nReason: ", Reason ),
             "\nПричина: ", Reason ),
         fail.
         fail.
     handleFileReadError(ErrorCode):-
     handleFileReadError(ErrorCode):-
         isDebugMode = true,
         isDebugMode = true, % режим отладки
         !,
         !,
         exceptionDump::dumpToStdOutput(ErrorCode),
         exceptionDump::dumpToStdOutput(ErrorCode),
         % dump to console for developer needs
         % выводим на консоль, поскольку режим отладки
         fail.
         fail.
     handleFileReadError(_ErrorCode):-
     handleFileReadError(_ErrorCode):-
         % program cannot handle the exception and it does not report about it .
         % программа не может обработать исключение и не информирует о нем
         fail.</vip>
         fail.</vip>


When '''fileSystem_api::cannotcreate''' exception is expected, the predicate '''exception::tryGetDescriptor''' is invoked exactly with such parameter to catch and handle such exception. In our case we use the output to console:
Когда предполагается исключение '''fileSystem_api::cannotcreate''', предикат '''exception::tryGetDescriptor''' вызывается именно с этим параметром для перехвата и обработки такого исключения. В нашем случае используется вывод на консоль:
 
<vip>stdIO::write("Cannot load file due to: ", ExceptionDescription,
    "\nFileName: ", FileName,
    "\nReason: ", Reason ),</vip>


with an explanation of a reason of the exception.
<vip>stdIO::write("Невозможно загрузить файл по причине: ", ExceptionDescription,
    "\nИмяФайла: ", FileName,
    "\nПричина: ", Reason ),</vip>


Please notice that since Visual Prolog 7.0 it is not necessary to clear exceptions, as all necessary information is stored in TraceId. This fact actually increases the performance of your program.
с объяснением причины исключения.


The full example presents in '''catchException\catchException.prj6''' project.
Обратите внимание, что нет необходимости в очистке следов исключения, поскольку вся необходимая информация сохраняется в TraceId. Этот факт значительно ускоряет работу программы.


==How to Raise Own Exceptions==
Полный пример содержится в проекте '''catchException\catchException.prj6'''.


Let us consider a program, that checks the size of a specified file. The PFC supply the predicate file::getFileProperties that can return the size of the specified file. If the size is zero, then we can raise an exception by the predicate exception::raise. It is also necessary to create a predicate, which will specify the exception. We have created myExceptionZeroFileSize for this purpose. The code of raising an exception will look like:
==Как вызвать исключение==
Рассмотрим программу, которая проверяет размер заданного файла. PFC предлагает предикат file::getFileProperties, который возвращает размер заданного файла. Если файл имеет нулевой размер, то мы можем вызвать исключение с помощью предиката exception::raise. Необходимо при этом создать предикат, который будет характеризовать исключение. С этой целью мы создаём предикат myExceptionZeroFileSize. Код, вызывающий исключение, будет выглядеть так:


<vip>clauses
<vip>clauses
    run():-
  run():-
        console::init(),
    console::init(),
        trap(file::getFileProperties(myFileName, _Attributes, Size, _Creation, _LastAccess, _LastChange),
    try
            ErrorCode,
      file::getFileProperties(myFileName,_Attributes,Size,_Creation,_LastAccess,_LastChange)
            handleFileGetPropertiesError(ErrorCode)),
    catch ErrorCode do
        Size = unsigned64(0, 0), % file size is zero
      handleFileGetPropertiesError(ErrorCode)
        !,
    end try,
        exception::raise(classInfo,myExceptionZeroFileSize,
 
            [namedValue(fileSystem_api::fileName_parameter, string(myFileName))]).
    Size = unsigned64(0, 0), % file size is zero
    run().</vip>
    !,
    exception::raise
        (
        classInfo,
        myExceptionZeroFileSize,
        [namedValue(fileSystem_api::fileName_parameter, string(myFileName))]
        ).
  run().</vip>


The first parameter of the predicate exception::raise is the predicate classInfo, which is generated by the IDE for any new class. It is, of course, a good idea to specify extra information, when an exception is generated. In our case the file name can be helpful, as a zero size belongs to the specified file.
Первый параметр предиката exception::raise - предикат classInfo, который генерируется средой  IDE для каждого нового класса. Для генерируемого исключения неплохо было бы определить дополнительную информацию, относящуюся к данному исключению. В нашем случае полезно имя файла, поскольку нулевой  размер связан с этим заданным файлом.


The predicate myExceptionZeroFileSize is created by the template:
Предикат myExceptionZeroFileSize создаётся по шаблону:


<vip>clauses
<vip>clauses
   myExceptionZeroFileSize(classInfo, predicate_Name(),
   myExceptionZeroFileSize
     "File size cannot be zero").</vip>
    (
    classInfo,
    predicate_Name(),
     "Размер файла не может быть нулевым"
    ).</vip>


That is, the first and the second parameters for exception predicates are always classInfo and predicate_Name() respectively, and the third parameter contains a text explanation of the exception reason.
Здесь первый и второй параметры предикатов исключений всегда есть classInfo и predicate_Name() соответственно, а третий параметр содержит текстовое пояснение причины исключения.


The full example presents in raiseException\raiseException.prj6''''''  project.
Полностью пример представлен в проекте '''raiseException\raiseException.prj6'''.


==How to Continue Another Exception==
==Продолжение другого исключения==


Let us consider a DLL program that reads a text file and returns its content as a return parameter. If an exception occurs, then the DLL continues it and adds extra information about DLL's version. The code to continue the exception will look like:
Рассмотрим программу, помещённую в DLL, которая читает текстовый файл и его содержимое передаёт в возвращаемом параметре. Если происходит исключение, то DLL продолжает его и добавляет информацию о версии DLL. Для продолжения исключения код выглядит так:


<vip>constants
<vip>constants
    dllVersion = "1.20.0.0".
  dllVersion = "1.20.0.0".
clauses
clauses
    loadFile(FileName) = FileContent :-
  loadFile(FileName) = FileContent :-
        trap(FileContent = file::readString(FileName, _IsUnicode),
    try
          ErrorCode,
      FileContent = file::readString(FileName, _IsUnicode)
          exception::continue(ErrorCode, classInfo, continuedFromDll,
    catch ErrorCode do
                [namedValue(version_Parameter,string(dllVersion))])).</vip>
      exception::continue(ErrorCode, classInfo, continuedFromDll,
      [namedValue(version_Parameter,string(dllVersion))])
    end try.</vip>


The predicate continuedFromDll is declared as:
Предикат continuedFromDll объявлен как:


<vip>predicates
<vip>predicates
    continuedFromDll : core::exception as "_ContinuedFromDll@12"</vip>
  continuedFromDll : core::exception as "_ContinuedFromDll@12"</vip>


and it is exported from the DLL. The implementation of the continuedFromDll predicate is created by a template ( the same as myExceptionZeroFileSizeabove):
и этот предикат экспортируется из DLL. Имплементация предиката continuedFromDll создаётся по шаблону (аналогично предикату myExceptionZeroFileSizeabove):


<vip>clauses
<vip>clauses
     continuedFromDll(classInfo, predicate_Name(),
  continuedFromDll
          "Exception continued from continueException.DLL").</vip>
     (
    classInfo,
    predicate_Name(),
    "Exception continued from continueException.DLL"
    ).</vip>


When the predicate exception::continue continues the exception, it adds extra information about dllVersion.
При продолжении исключения предикат exception::continue добавляет информацию о версии DLL.


The full example presents in '''continueException\continueException.prj6''' project.
Полностью пример представлен в проекте '''continueException\continueException.prj6'''.


Let us look how to catch such continued exception. The code is similar to the code discussed above and we will focus on the differences here.
Посмотрим теперь, как перехватывать такого рода исключения. Код в принципе похож на обсуждавшийся выше, поэтому мы сосредоточимся на различиях.


<vip>constants
<vip>constants
    myFileName = "my.txt".
  myFileName = "my.txt".
clauses
clauses
    run():-
  run():-
        console::init(),
    console::init(),
        initExceptionState(exception::getExceptionState()),
    initExceptionState(exception::getExceptionState()),
        trap(MyTxtFileContent = loadFile(myFileName),
    try
            ErrorCode,
      MyTxtFileContent = loadFile(myFileName)
            handleFileReadError(ErrorCode)),
    catch TraceID do
        !,
      handleFileReadError(TraceID)
        stdIO::write("The content of ",myFileName,"is:\n",MyTxtFileContent).
    end try,
    run().
    !,
    stdIO::write("The content of ",myFileName,"is:\n",MyTxtFileContent).
  run().


class predicates
class predicates
    handleFileReadError : ( exception::traceID TraceId )failure .
  handleFileReadError : ( exception::traceID TraceId )failure .
clauses
clauses
    handleFileReadError(TraceId):-
  handleFileReadError(TraceId):-
        DescriptorContinued = exception::tryGetDescriptor(TraceId, continuedFromDll),
    DescriptorContinued = exception::tryGetDescriptor(TraceId, continuedFromDll),
        ErrorDescriptorInformation = exception::tryGetErrorDescriptorInformation(TraceId),
    ErrorDescriptorInformation = exception::tryGetErrorDescriptorInformation(TraceId),
        ContinueException = ErrorDescriptorInformation:tryGetContinueException(),
    ContinueException = ErrorDescriptorInformation:tryGetContinueException(),
        !, %file cannot be loaded
    !, % ясно, что файл не загрузился
        exception::descriptor(_ErrorCodeContinued,
    exception::descriptor
            _ClassInfoContinued,
      (_ErrorCodeContinued,
            _ExceptionContinued,
      _ClassInfoContinued,
            _KindContinued,
      _ExceptionContinued,
            ExtraInfoContinued,
      _KindContinued,
            _,
      ExtraInfoContinued,
            _GMTTimeContinued,
      _,
            ExceptionDescriptionContinued,
      _GMTTimeContinued,
            _ThreadIdContinued) = DescriptorContinued,
      ExceptionDescriptionContinued,
        Version = namedValue::mapLookUp(ExtraInfoContinued, version_Parameter, string("")),
      _ThreadIdContinued) = DescriptorContinued,
        stdIO::write("Exception continued : ",ExceptionDescriptionContinued,
      Version = namedValue::mapLookUp(ExtraInfoContinued, version_Parameter, string("")),
            "\nDllVersion: ", Version,"\n"),
      stdIO::write("Продолженное исключение : ",ExceptionDescriptionContinued,"\nВерсия Dll: ", Version,"\n"),
        ExtraInfo = ContinueException:getExtraInfo(),
      ExtraInfo = ContinueException:getExtraInfo(),
        ExceptionDescription = ContinueException:getExceptionDescription(),
      ExceptionDescription = ContinueException:getExceptionDescription(),
        FileName = namedValue::mapLookUp(ExtraInfo,
      FileName = namedValue::mapLookUp(ExtraInfo,fileSystem_api::fileName_parameter, string("")),
        fileSystem_api::fileName_parameter, string("")),
      Reason = namedValue::mapLookUp(ExtraInfo,common_exception::errorDescription_parameter, string("")),
        Reason = namedValue::mapLookUp(ExtraInfo,
      stdIO::write
            common_exception::errorDescription_parameter, string("")),
        (
        stdIO::write("Cannot load file due to: ",ExceptionDescription,
        "Файл не загружен по причине: ",ExceptionDescription,
            "\nFile Name: ", FileName,
        "\nИмя файла: ", FileName,
            "\nReason: ", Reason ),
        "\nПричина: ", Reason ),
        fail.
      fail.
    handleFileReadError(TraceId):-
  handleFileReadError(TraceId):-
        isDebugMode = true,
    isDebugMode = true, % режим отладки
        !,
    !,
        exceptionDump::dumpToStdOutput(TraceId),
    exceptionDump::dumpToStdOutput(TraceId),
        fail.
    fail.
    handleFileReadError(_TraceId):-
  handleFileReadError(_TraceId):-
        fail.</vip>
    fail.</vip>
 
Мы пытаемся здесь найти исключение '''continuedFromDll''' и мы вызываем продолжающееся предикатом исключение '''tryGetContinueException'''. Это ясно показывает, что, если исключение продолжающееся, то мы можем получить дополнительную информацию касательно самого исключения.


In the code we try to find '''continuedFromDll''' exception and we retrieve the continued exception by the predicate '''tryGetContinueException'''. This clearly shows that if an exception was continued, then we can gain more information about the exception.
Полностью пример представлен в проекте '''continueException\testContinuedException\testContinuedException.prj6'''. Необходимо построить сначала приложение '''continueException\continueException.prj6''' перед тем как вызывать на выполнение исполняемое приложение testContinuedException.


The full example presents in '''continueException\testContinuedException\testContinuedException.prj6''' project. It is necessary to build '''continueException\continueException.prj6''' before running testContunedException executable.
==trap vs try==
Начиная с версии 7.0 появилась конструкция '''try/catch/finally''', которая заменяет встроенные предикаты '''trap/3''' и '''finally/2'''.


==Ссылки==
==Ссылки==
[[en:Exceptions handling]]
[[en:Exceptions Handling]]
[[Категория:VipLanguage]]
[[Категория:VipLanguage]]
[[Категория:VipРуководства]]
[[Категория:VipРуководства]]

Текущая версия на 12:31, 10 января 2008

Исключение - это отклонение программы от маршрута "нормального" выполнения. Пакет exception из состава PFC содержит предикаты помогающие обрабатывать и распространять исключения, которые возникают в программах на Прологе. Это руководство объясняет:

  • Как обрабатывать исключения;
  • Как возбуждать ваши собственные исключения;
  • Как продолжать другое исключение.

Как перехватывать исключения

Рассмотрим программу, которая читает текстовый файл и выводит его содержимое на консоль. PFC предлагает предикат file::readString, который позволяет выполнить эту задачу. Однако, некоторые обстоятельства могут помешать эту задачу; например, заданное имя файла ссылается на несуществующий файл. Когда предикат file::readString не может выполнить задачу, он генерирует исключение.

Visual Prolog предлагает конструкцию try/catch (см. Try вместо Trap), которая перехватывает исключение и позволяет его обработать. Детальное описание этой конструкции можно найти в справке по Visual Prolog (Language Reference -> Exception Handling).

Соответственно, код для перехвата исключения будет выглядеть так:

try  
    MyTxtFileContent = file::readString(myFileName, _IsUnicode)
catch ErrorCode do
    handleFileReadError(ErrorCode)
end try,
...

Самое интересное здесь это - имплементация предиката handleFileReadError:

class predicates
    handleFileReadError : (exception::traceID TraceId) failure.
clauses
    handleFileReadError(TraceId):-
        Descriptor = exception::tryGetDescriptor(TraceId, fileSystem_api::cannotcreate),
        !, % файл не может быт загружен
        exception::descriptor(_ErrorCode, % ErrorCode используется, если пользователь сам вызывает errorExit.
            _ClassInfo, % информация о классе, который возбудил исключение.
            _Exception, % на самом деле это fileSystem_api::cannotcreate,
            % но параметр не может участвовать в сравнении с помощью ' = '.
            % смотрите exceptionState::equals
            _Kind, % исключение может быть возбуждено или продолжено
            ExtraInfo,
            _TraceId, % здесь идентификатор ошибки, но необходимости в проверке нет
            _GMTTime, % время возникновения исключения
            ExceptionDescription,
            _ThreadId) = Descriptor,
        FileName = namedValue::mapLookUp(ExtraInfo,
        fileSystem_api::fileName_parameter, string("")),
        Reason = namedValue::mapLookUp(ExtraInfo,
        common_exception::errorDescription_parameter, string("")),
        stdIO::write("Невозможно загрузить файл по причине: ",ExceptionDescription,
            "\nИмя файла: ", FileName,
            "\nПричина: ", Reason ),
        fail.
    handleFileReadError(ErrorCode):-
        isDebugMode = true, % режим отладки
        !,
        exceptionDump::dumpToStdOutput(ErrorCode),
        % выводим на консоль, поскольку режим отладки
        fail.
    handleFileReadError(_ErrorCode):-
        % программа не может обработать исключение и не информирует о нем
        fail.

Когда предполагается исключение fileSystem_api::cannotcreate, предикат exception::tryGetDescriptor вызывается именно с этим параметром для перехвата и обработки такого исключения. В нашем случае используется вывод на консоль:

stdIO::write("Невозможно загрузить файл по причине: ", ExceptionDescription,
    "\nИмяФайла: ", FileName,
    "\nПричина: ", Reason ),

с объяснением причины исключения.

Обратите внимание, что нет необходимости в очистке следов исключения, поскольку вся необходимая информация сохраняется в TraceId. Этот факт значительно ускоряет работу программы.

Полный пример содержится в проекте catchException\catchException.prj6.

Как вызвать исключение

Рассмотрим программу, которая проверяет размер заданного файла. PFC предлагает предикат file::getFileProperties, который возвращает размер заданного файла. Если файл имеет нулевой размер, то мы можем вызвать исключение с помощью предиката exception::raise. Необходимо при этом создать предикат, который будет характеризовать исключение. С этой целью мы создаём предикат myExceptionZeroFileSize. Код, вызывающий исключение, будет выглядеть так:

clauses
  run():-
    console::init(),
    try
      file::getFileProperties(myFileName,_Attributes,Size,_Creation,_LastAccess,_LastChange)
    catch ErrorCode do
      handleFileGetPropertiesError(ErrorCode)
    end try,
 
    Size = unsigned64(0, 0), % file size is zero
    !,
    exception::raise
        (
        classInfo,
        myExceptionZeroFileSize,
        [namedValue(fileSystem_api::fileName_parameter, string(myFileName))]
        ).
  run().

Первый параметр предиката exception::raise - предикат classInfo, который генерируется средой IDE для каждого нового класса. Для генерируемого исключения неплохо было бы определить дополнительную информацию, относящуюся к данному исключению. В нашем случае полезно имя файла, поскольку нулевой размер связан с этим заданным файлом.

Предикат myExceptionZeroFileSize создаётся по шаблону:

clauses
  myExceptionZeroFileSize
    (
    classInfo,
    predicate_Name(),
    "Размер файла не может быть нулевым"
    ).

Здесь первый и второй параметры предикатов исключений всегда есть classInfo и predicate_Name() соответственно, а третий параметр содержит текстовое пояснение причины исключения.

Полностью пример представлен в проекте raiseException\raiseException.prj6.

Продолжение другого исключения

Рассмотрим программу, помещённую в DLL, которая читает текстовый файл и его содержимое передаёт в возвращаемом параметре. Если происходит исключение, то DLL продолжает его и добавляет информацию о версии DLL. Для продолжения исключения код выглядит так:

constants
  dllVersion = "1.20.0.0".
clauses
  loadFile(FileName) = FileContent :-
    try
       FileContent = file::readString(FileName, _IsUnicode)
    catch ErrorCode do
       exception::continue(ErrorCode, classInfo, continuedFromDll,
       [namedValue(version_Parameter,string(dllVersion))])
    end try.

Предикат continuedFromDll объявлен как:

predicates
  continuedFromDll : core::exception as "_ContinuedFromDll@12"

и этот предикат экспортируется из DLL. Имплементация предиката continuedFromDll создаётся по шаблону (аналогично предикату myExceptionZeroFileSizeabove):

clauses
  continuedFromDll
    (
    classInfo,
    predicate_Name(),
    "Exception continued from continueException.DLL"
    ).

При продолжении исключения предикат exception::continue добавляет информацию о версии DLL.

Полностью пример представлен в проекте continueException\continueException.prj6.

Посмотрим теперь, как перехватывать такого рода исключения. Код в принципе похож на обсуждавшийся выше, поэтому мы сосредоточимся на различиях.

constants
  myFileName = "my.txt".
clauses
  run():-
    console::init(),
    initExceptionState(exception::getExceptionState()),
    try
      MyTxtFileContent = loadFile(myFileName)
    catch TraceID do
      handleFileReadError(TraceID)
    end try,
    !,
    stdIO::write("The content of ",myFileName,"is:\n",MyTxtFileContent).
  run().
 
class predicates
  handleFileReadError : ( exception::traceID TraceId )failure .
clauses
  handleFileReadError(TraceId):-
    DescriptorContinued = exception::tryGetDescriptor(TraceId, continuedFromDll),
    ErrorDescriptorInformation = exception::tryGetErrorDescriptorInformation(TraceId),
    ContinueException = ErrorDescriptorInformation:tryGetContinueException(),
    !, % ясно, что файл не загрузился
    exception::descriptor
      (_ErrorCodeContinued,
      _ClassInfoContinued,
      _ExceptionContinued,
      _KindContinued,
      ExtraInfoContinued,
      _,
      _GMTTimeContinued,
      ExceptionDescriptionContinued,
      _ThreadIdContinued) = DescriptorContinued,
      Version = namedValue::mapLookUp(ExtraInfoContinued, version_Parameter, string("")),
      stdIO::write("Продолженное исключение : ",ExceptionDescriptionContinued,"\nВерсия Dll: ", Version,"\n"),
      ExtraInfo = ContinueException:getExtraInfo(),
      ExceptionDescription = ContinueException:getExceptionDescription(),
      FileName = namedValue::mapLookUp(ExtraInfo,fileSystem_api::fileName_parameter, string("")),
      Reason = namedValue::mapLookUp(ExtraInfo,common_exception::errorDescription_parameter, string("")),
      stdIO::write
        (
        "Файл не загружен по причине: ",ExceptionDescription,
        "\nИмя файла: ", FileName,
        "\nПричина: ", Reason ),
      fail.
  handleFileReadError(TraceId):-
    isDebugMode = true, % режим отладки
    !,
    exceptionDump::dumpToStdOutput(TraceId),
    fail.
  handleFileReadError(_TraceId):-
    fail.

Мы пытаемся здесь найти исключение continuedFromDll и мы вызываем продолжающееся предикатом исключение tryGetContinueException. Это ясно показывает, что, если исключение продолжающееся, то мы можем получить дополнительную информацию касательно самого исключения.

Полностью пример представлен в проекте continueException\testContinuedException\testContinuedException.prj6. Необходимо построить сначала приложение continueException\continueException.prj6 перед тем как вызывать на выполнение исполняемое приложение testContinuedException.

trap vs try

Начиная с версии 7.0 появилась конструкция try/catch/finally, которая заменяет встроенные предикаты trap/3 и finally/2.

Ссылки