- Documentation
- Reference manual
- Packages
- A C++ interface to SWI-Prolog
- A C++ interface to SWI-Prolog
- Summary of changes between Versions 1 and 2
- A simple example
- Sample code
- Introduction
- The life of a PREDICATE
- Overview
- Examples
- Rationale for changes from version 1
- Porting from version 1 to version 2
- The class PlFail
- Overview of accessing and changing values
- The class PlRegister
- The class PlQuery
- The PREDICATE and PREDICATE_NONDET macros
- Exceptions
- Embedded applications
- Considerations
- Conclusions
- A C++ interface to SWI-Prolog
- A C++ interface to SWI-Prolog
1.15 Exceptions
See also Prolog exceptions in foreign code.
Prolog exceptions are mapped to C++ exceptions using the class
PlException (a subclass of PlExceptionBase to
represent the Prolog exception term. All type-conversion functions of
the interface raise Prolog-compliant exceptions, providing decent
error-handling support at no extra work for the programmer.
For some commonly used exceptions, convenience functions have been
created to exploit both their constructors for easy creation of these
exceptions. If you wish to trap these, you should use
PlException or PlExceptionBase and then look
for the appropriate error name. For example, the following code catches
"type_error" and passes all other exceptions:
try
{ do_something(...);
} catch ( const PlException& e)
{ PlTerm e_t = e.term();
PlAtom ATOM_type_error("type_error");
// e_t.name() == PlAtom("error") && e_t.arity() == 2
if ( e_t[1].name() == ATOM_type_error) )
{ ... // expected type and culprit are \exam{e_t[1][1]} and \exam{e_t[1][2]}
} else throw;
}
The convenience functions are PlTypeEror() and PlDomainError(), PlDomainError(), PlInstantiationError(), PlExistenceError(), PlUninstantiationError(), PlRepresentationError(), PlPermissionError(), PlResourceError(), PlUnknownError().
There is also a PlGeneralError(inside_term) that creates
error(Inside_term,_) terms and is used by the other error
convience functions.
The easiest way to access the exception from PlCall()
is by using PlExceptionFromQid - you can then check for an
exception by using the PlException::is_null() method.
To throw an exception, create an instance of PlException
and use throw. This is intercepted by the PREDICATE macro
and turned into a Prolog exception. See section
1.17.2.
char *data = "users";
throw PlGeneralError(PlCompound("no_database", PlTerm(data)));
Sometimes, you may need to more control over the exception term or
you may need to copy a term (e.g., PL_clear_exception() clears
the error term, so it may need to be copied for a rethrow); for this,
use
PlExceptionFromTerm(). Note that unlike the other ways of
creating exceptions, this does not create a term of the form
error(Term,_); if you wish to create your own form of an
error, you should use PlGeneralError(). But if you need to create
a term that isn't the functor error, you can do something
like this:
throw PlExceptionFromTerm(
PlCompound("my_weird_error_term",
PlTermv(t, PlTerm_var())));
1.15.1 The class PlException
This subclass of PlExceptionBase is used to represent
exceptions.
1.15.1.1 PlException class hierarchy
The various exceptions are arranged into a hierarchy as follows. ForPlException, there are convenience functions that create
and wrap a Prolog term, similar to the PL_domain_error(), etc.
The hierarchy allows catch statements to easily handle
combinations.
A PlException object contains a Prolog term, so its
what() method must be called either
within a Prolog predicate or within the context of a PlEngine
(and PlFrame; see section
1.16). The term is copied so that it is available outside of the
context of the frame that created it.
You cannot create a PlExceptionBase or PlException
because their constructors are protected.
In this diagram, names with () are functions; the others
are classes.
std::exception
*-- PlExceptionBase
*-- PlException
| *.. PlExceptionFromTerm
| *.. PlExceptionFromQid
| *.. PlDomainError()
| *.. PlExistenceError()
| *.. PlGeneralError()
| *.. PlInstantiationError()
| *.. PlPermissionError()
| *.. PlRepresentationError()
| *.. PlResourceError()
| *.. PlTypeError()
| *.. PlUninstantiationError()
| *.. PlUnknownError()
*-- PlExceptionFailBase
| *-- PlExceptionFail
| *-- PlFail
*-- PlEngineInitialisationFailed
*-- PlOpenForeignFrameFailed
Note that everything under PlException can contain a
Prolog term; if the what() method is
called, it must be within the context of a Prolog frame. If you wish to
pass the exception outside the frame, you can use the set_what_str()
method to avoid evaluating the term after it has been freed by Prolog:
try
{ PlCall("p(123)");
...
} catch ( PlException &ex )
{ ex.set_what_str();
throw; // rethrow the exception
}
Currently defined methods are:
- PlException :: PlException(const PlTerm &t)
- Create an exception from a general Prolog term. This provides the
interface for throwing any Prolog terms as an exception. This
constructor is protected; instead you should use
PlExceptionFromTermorPlExceptionFromQid. - char* what()
- See ctypestd::exception::what(). Note that if this is called outside the Prolog frame where the exception was created, there must have been a call to PlException::set_what_str() inside the Prolog frame.
- std::string as_string()
- The exception is translated into a message as produced by
print_message/2.
Note that if this is called outside the Prolog frame where the exception
was created, there must have been a call to PlException::set_what_str()
inside the Prolog frame. See also std::exception::what().
...; try { PlCall("consult(load)"); } catch ( const PlException& ex ) { cerr << ex.as_string() << endl; } - int plThrow()
- Used in the PREDICATE() wrapper to pass the exception to Prolog. See PL_raise_exception().
- void set_what_str()
-
1.15.1.2 The function PlTypeError
A type error expresses that a term does not satisfy the expected basic Prolog type.
- PlTypeError :: PlTypeError(const std::string& expected, const PlTerm &actual)
- Creates an ISO standard Prolog error term expressing the expected type and actual term that does not satisfy this type.
1.15.1.3 The function PlDomainError
A domain error expresses that a term satisfies the basic
Prolog type expected, but is unacceptable to the restricted domain
expected by some operation. For example, the standard Prolog open/3
call expect an io_mode (read, write, append, ... ). If an
integer is provided, this is a type error, if an atom other
than one of the defined io-modes is provided it is a domain error.
- PlDomainError :: PlDomainError(const std::string& expected, const PlTerm &actual)
- Creates an ISO standard Prolog error term expressing a the expected domain and the actual term found.