Skip to content

Exception

tuprolog.solve.exception

Exceptions raised while solving queries: ISO Prolog errors, halts, timeouts, and warnings.

Prolog programs signal problems by throwing terms (throw/1), which callers may catch (catch(Goal, Catcher, Recovery) runs Recovery if Goal throws a term unifying with Catcher). The ISO standard fixes the shape of the terms built-in predicates throw: error(Type, Extra), where Type says what went wrong (e.g. type_error(integer, a): an integer was expected, a was found) and Extra carries implementation-defined details (2P-Kt puts a human-readable message there). See tuprolog.solve.exception.error for each kind of error.

In this library each such problem is a JVM exception (raised and caught as a Python exception) descending from ResolutionException:

  • LogicError: an ISO error, i.e. a thrown error(Type, Extra) term (subclasses in tuprolog.solve.exception.error);
  • HaltException: the solver was stopped, e.g. by halt/0,1;
  • TimeOutException: a query exceeded its time limit;
  • Warning (import it explicitly, as it shadows Python's built-in name): a non-fatal problem, reported on the solver's warnings channel rather than stopping resolution (subclasses in tuprolog.solve.exception.warning).

Solvers do not raise these exceptions when solving: an error ends the solutions with a halt solution carrying the exception (see tuprolog.solve.Solution), while Solver.query raises it. Primitives written in Python raise them (or reply with them, see tuprolog.solve.primitive) to signal errors. tuprolog.errors makes them also instances of Python classes (e.g. a logic type_error is a tuprolog.errors.PrologTypeError and a built-in TypeError), for except.

Examples:

>>> from tuprolog.solve.prolog import prolog_solver
>>> solver = prolog_solver()
>>> solution = solver.solve_once("X is 1 / 0")
>>> solution.is_halt
True
>>> error = solution.get_exception()
>>> isinstance(error, LogicError), error.type
(True, evaluation_error(zero_divisor))
>>> solver.solve_once("catch(X is 1 / 0, error(E, _), true)")["E"]
evaluation_error(zero_divisor)
>>> try:
...     list(solver.query("atom_length(X, L)"))
... except ResolutionException as e:
...     print(e.error_struct.args[0])
instantiation_error
See Also

tuprolog.solve.exception.error and tuprolog.solve.exception.warning, for the subclasses; tuprolog.errors, for the Python exception classes; 2P-Kt's documentation on errors and exceptions.

HaltException module-attribute

HaltException = _exceptions.HaltException

The exception stopping a solver, e.g. raised by halt/0 and halt/1.

Members (snake_case aliases as well): exit_status, the integer status (halt/1's argument, 0 by default), besides those of ResolutionException.

Examples:

>>> from tuprolog.solve.prolog import prolog_solver
>>> error = prolog_solver().solve_once("halt(3)").get_exception()
>>> isinstance(error, HaltException), error.exit_status
(True, 3)

LogicError module-attribute

LogicError = _exceptions.LogicError

An ISO Prolog error: the exception a predicate throws as the term error(Type, Extra).

Subclasses (in tuprolog.solve.exception.error) model each family of ISO errors, telling them by Type's functor (e.g. type_error/2 is a TypeError). Prolog code catches them with catch(Goal, error(Type, _), Recovery).

Members (snake_case aliases as well), besides those of ResolutionException:

  • type: the error type, a tuprolog.core.Struct such as type_error(integer, a) or instantiation_error;
  • extra_data: the extra data (a tuprolog.core.Term, usually the message as an atom), or None;
  • error_struct: the thrown term, error(Type, Extra).

LogicError.of(...) is 2P-Kt's factory building the subclass matching an error type; the factories in tuprolog.solve.exception.error are the handier way to build errors.

Examples:

>>> from tuprolog.solve.prolog import prolog_solver
>>> error = prolog_solver().solve_once("atom_length(f, a)").get_exception()
>>> isinstance(error, LogicError)
True
>>> error.type
type_error(integer, a)
>>> error.error_struct.functor
'error'

ResolutionException module-attribute

ResolutionException = _exceptions.ResolutionException

The base of the exceptions that may occur while solving a query.

Members (snake_case aliases as well):

  • message, cause: the description, and the exception causing this one (if any);
  • context: the tuprolog.solve.ExecutionContext in which the exception occurred, and contexts, the stack of contexts, innermost first (one per nested resolution);
  • logic_stack_trace: the goals being solved when the exception occurred, innermost first, as tuprolog.core.Structs;
  • update_context(context, index), update_last_context(context), push_context(context): copies of the exception with a changed or extended stack of contexts (exceptions are immutable).

Subclasses: LogicError, HaltException, TimeOutException, and Warning.

TimeOutException module-attribute

TimeOutException = _exceptions.TimeOutException

The exception ending a query that exceeded its time limit.

Members (snake_case aliases as well): exceeded_duration, the time limit exceeded (in milliseconds), besides those of ResolutionException.

Examples:

>>> from tuprolog.solve.prolog import prolog_solver
>>> error = prolog_solver().solve_once("repeat, fail", 50).get_exception()
>>> isinstance(error, TimeOutException), error.exceeded_duration
(True, 50)