This module provides SICStus Prolog-compatible
:- block BlockSpec, ...
declarations for delaying predicate calls if
certain arguments are unbound.
- See also
- - https://sicstus.sics.se/sicstus/docs/3.12.11/html/sicstus/Block-Declarations.html
- block +Heads
- Declare predicates to suspend on certain modes. The argument is,
like meta_predicate/1, a comma-separated list of modes
(BlockSpecs). Calls to the predicate is suspended if at least
one of the conditions implies by a blockspec evaluated to
true
. A blockspec evaluated to true
iff all arguments
specified as `-' are unbound.
Multiple BlockSpecs for a single predicate can appear in one or
more :- block declarations. The predicate is suspended untill
all mode patterns that apply to it are satisfied.
The implementation is realised by creating a wrapper that checks
the block conditions and either calls the original predicate
immediately (if none of the block conditions were true) or uses
attributed variables to delay re-evaluating the block condition
until any of the arguments in question are bound.
- Compatibility
- - SICStus Prolog
- block_wrapper_clauses(+Module, +Head, -Clauses) is det[private]
- Build a list of clauses that define a block wrapper around
predicate Head in Module. If a wrapper for this predicate has
already been defined, Clauses is an empty list.
- block_wrapper_clause(+Module, +Name, +HelperHead, -Clause) is nondet[private]
- Generate the clauses for the wrapper. The blockspecs are
translated into a helper predicate, where each clause checks one
block condition. If a block condition is true, attributes are
added to all arguments marked as
-
, so that once any of them
are bound, the predicate is called again and the block
conditions are re-evaluated. If no block condition was true,
the helper predicate fails.
Finally, an initialization clause is generated that sets up the
actual wrapper. This wrapper first calls the helper predicate
to check all block conditions and delay the call if necessary.
If the helper predicate fails (i. e. no block condition was
true), the wrapped predicate is called immediately.
The wrapper must be set up in an initialization clause and not
as part of the term expansion, because wrap_predicate/4 wrappers
are not retained in saved states, which would cause block
declarations to break when loading a saved state.
- find_args_to_block_on(+BlockArgs, +HeadArgs, -ArgsToBlockOn) is semidet[private]
- Collect into ArgsToBlockOn all arguments from HeadArgs for which
the corresponding argument in BlockArgs is
-
, indicating that
the argument is part of the block condition.
- args_to_var_conditions(+ArgsToBlockOn, -Conditions, ?ConditionsTail) is semidet[private]
- Convert a list of arguments into a conjunction of var/1 checks
that succeeds if all arguments are unbound variables.
This effectively generates an unrolled version of
maplist(var, ArgsToBlockOn), ConditionsTail
.
- args_to_suspend_calls(+ArgsToBlockOn, -IsAlreadyUnblocked, +BlockedGoal, -SuspendCalls, +Tail) is semidet[private]
- Build a sequence of calls that delays BlockedGoal until any
variable in ArgsToBlockOn is bound. IsAlreadyUnblocked should be
an unbound fresh variable - it is passed directly to unblock/2,
which will bind the variable so that the same blocked goal is
not called again by another unblock/2 call from the same group.
- rename_clause(+Clause, +Prefix, -Renamed) is det[private]
- Rename a clause by prefixing its old name wit h Prefix.