This module provides the developers interface for the directive
predicate_options/3. This directive allows us to specify that, e.g.,
open/4 processes options using the 4th argument and supports the option
type
using the values text
and binary
. Declaring options that are
processed allows for more reliable handling of predicate options and
simplifies porting applications. This library provides the following
functionality:
Below, we describe some use-cases.
- Quick check of a program
-
This scenario is useful as an occasional check or to assess problems
with option-handling for porting an application to SWI-Prolog. It
consists of three steps: loading the program (1 and 2), deriving
option handling for application predicates (3) and running the
checker (4).
1 ?- [load].
2 ?- autoload.
3 ?- derive_predicate_options.
4 ?- check_predicate_options.
- Add declarations to your program
-
Adding declarations about option processes improves the quality of
the checking. The analysis of derive_predicate_options/0 may miss
options and does not derive the types for options that are processed
in Prolog code. The process is similar to the above. In steps 4 and
further, the inferred declarations are listed, inspected and added to
the source code of the module.
1 ?- [load].
2 ?- autoload.
3 ?- derive_predicate_options.
4 ?- derived_predicate_options(module_1).
5 ?- derived_predicate_options(module_2).
6 ?- ...
- Declare option processing requirements
-
If an application requires that open/4 needs to support
lock(write)
,
it may do so using the directive below. This directive raises an
exception when loaded on a Prolog implementation that does not support
this option.
:- current_predicate_option(open/4, 4, lock(write)).
- See also
- - library(option) for accessing options in Prolog code.
- predicate_options(:PI, +Arg, +Options) is det
- Declare that the predicate PI processes options on Arg. Options
is a list of options processed. Each element is one of:
- Option(ModeAndType)
PI processes Option. The option-value must comply to
ModeAndType. Mode is one of + or - and Type is a type as
accepted by must_be/2.
- pass_to(:PI,Arg)
The option-list is passed to the indicated predicate.
Below is an example that processes the option header(boolean)
and passes all options to open/4:
:- predicate_options(write_xml_file/3, 3,
[ header(boolean),
pass_to(open/4, 4)
]).
write_xml_file(File, XMLTerm, Options) :-
open(File, write, Out, Options),
( option(header(true), Options, true)
-> write_xml_header(Out)
; true
),
...
This predicate may only be used as a directive and is
processed by expand_term/2. Option processing can be
specified at runtime using assert_predicate_options/3, which is
intended to support program analysis.
- assert_predicate_options(:PI, +Arg, +Options, ?New) is semidet
- As predicate_options(:PI, +Arg, +Options). New is a boolean
indicating whether the declarations have changed. If New is
provided and
false
, the predicate becomes semidet and fails
without modifications if modifications are required.
- current_option_arg(:PI, ?Arg) is nondet
- True when Arg of PI processes predicate options. Which options
are processed can be accessed using current_predicate_option/3.
- current_predicate_option(:PI, ?Arg, ?Option) is nondet
- True when Arg of PI processes Option. For example, the following
is true:
?- current_predicate_option(open/4, 4, type(text)).
true.
This predicate is intended to support conditional compilation
using if/1 ... endif/0. The predicate
current_predicate_options/3 can be used to access the full
capabilities of a predicate.
- check_predicate_option(:PI, +Arg, +Option) is det
- Verify predicate options at runtime. Similar to
current_predicate_option/3, but intended to support runtime
checking.
- Errors
- -
existence_error(option, OptionName)
if the option is not
supported by PI. - -
type_error(Type, Value)
if the option is supported but
the value does not match the option type. See must_be/2.
- current_predicate_options(:PI, ?Arg, ?Options) is nondet
- True when Options is the current active option declaration for
PI on Arg. See predicate_options/3 for the argument
descriptions. If PI is ground and refers to an undefined
predicate, the autoloader is used to obtain a definition of the
predicate.
- derived_predicate_options(:PI, ?Arg, ?Options) is nondet
- Derive option arguments using static analysis. True when Options
is the current derived active option declaration for PI on
Arg.
- expand_pass_to_options(+OptionsIn, +Module, -OptionsOut)// is det[private]
- Expand the options of
pass_to(PI,Arg)
if PI does not refer to a
public predicate.
- derived_predicate_options(+Module) is det
- Derive predicate option declarations for a module. The derived
options are printed to the
current_output
stream.
- retractall_predicate_options is det
- Remove all dynamically (derived) predicate options.
- check_predicate_options is det
- Analyse loaded program for erroneous options. This predicate
decompiles the current program and searches for calls to
predicates that process options. For each option list, it
validates whether the provided options are supported and
validates the argument type. This predicate performs partial
dataflow analysis to track option-lists inside a clause.
- See also
- - derive_predicate_options/0 can be used to derive
declarations for predicates that pass options. This
predicate should normally be called before
check_predicate_options/0.
- derive_predicate_options is det
- Derive new predicate option declarations. This predicate
analyses the loaded program to find clauses that process options
using one of the predicates from library(option) or passes
options to other predicates that are known to process options.
The process is repeated until no new declarations are retrieved.
- See also
- - autoload/0 may be used to complete the loaded program.
- check_predicate_options(:PredicateIndicator) is det
- Verify calls to predicates that have options in all clauses of
the predicate indicated by PredicateIndicator.
- check_clause(+Clause, +Module, +Ref, +Action) is det[private]
- Action is one of
- decl
- Create additional declarations
- check
- Produce error messages
- check_body(+Body, +Module, +TermPos, +Action)[private]
- check_called_by(+CalledBy, +M, +Action) is det[private]
- Handle results from prolog:called_by/2.
- check_options(:Predicate, +OptionArg, +Options, +ArgPos, +Action)[private]
- Verify the list Options, that is passed into Predicate on
argument OptionArg. ArgPos is a term-position term describing
the location of the Options list. If Options is a partial list,
the tail is annotated with
pass_to(PI, OptArg)
.
- annotate(+Var, +Term) is det[private]
- Use constraints to accumulate annotations about variables. If
two annotated variables are unified, the attributes are joined.
- option_decl(:Head, +Action) is det[private]
- Add new declarations based on attributes left by the analysis
pass. We do not add declarations for system modules or modules
that already contain static declarations.
- To be done
- - Should we add a mode to include generating declarations
for system modules and modules with static declarations?
- resolve_module(:PI, -DefPI) is det[private]
- Find the real predicate indicator pointing to the definition
module of PI. This is similar to using predicate_property/3 with
the property imported_from, but using
'$get_predicate_attribute'/3 avoids auto-importing the
predicate.