142 lines
4.2 KiB
Prolog
142 lines
4.2 KiB
Prolog
/* Part of SWI-Prolog
|
|
|
|
Author: Jan Wielemaker
|
|
E-mail: J.Wielemaker@cs.vu.nl
|
|
WWW: http://www.swi-prolog.org
|
|
Copyright (C): 2011, VU University Amsterdam
|
|
|
|
This program is free software; you can redistribute it and/or
|
|
modify it under the terms of the GNU General Public License
|
|
as published by the Free Software Foundation; either version 2
|
|
of the License, or (at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public
|
|
License along with this library; if not, write to the Free Software
|
|
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
|
|
As a special exception, if you link this library with other files,
|
|
compiled with a Free Software compiler, to produce an executable, this
|
|
library does not by itself cause the resulting executable to be covered
|
|
by the GNU General Public License. This exception does not however
|
|
invalidate any other reasons why the executable file might be covered by
|
|
the GNU General Public License.
|
|
*/
|
|
|
|
:- module(predopts,
|
|
[
|
|
]).
|
|
|
|
:- multifile
|
|
predicate_options:option_decl/3,
|
|
predicate_options:pred_option/3.
|
|
:- multifile % provided by library(predicate_options)
|
|
system:predicate_option_type/2,
|
|
system:predicate_option_mode/2.
|
|
|
|
:- public
|
|
option_clauses//4.
|
|
|
|
%% expand_predicate_options(:PI, +Arg, +OptionList, -Clauses) is det.
|
|
%
|
|
% Term-expansion code for predicate_options(PI, Arg, OptionList).
|
|
|
|
expand_predicate_options(PI, Arg, Options,
|
|
[ predicate_options:option_decl(Head, M, Arg),
|
|
(:-multifile(M:'$pred_option'/4))
|
|
| OptionClauses
|
|
]) :-
|
|
canonical_pi(PI, CPI),
|
|
prolog_load_context(module, M0),
|
|
strip_module(M0:CPI, M, Name/Arity),
|
|
functor(Head, Name, Arity),
|
|
( is_list(Options)
|
|
-> true
|
|
; throw(error(type_error(list, Options), _))
|
|
),
|
|
phrase(option_clauses(Options, Head, M, Arg), OptionClauses0),
|
|
qualify_list(OptionClauses0, M0, OptionClauses).
|
|
|
|
qualify_list([], _, []).
|
|
qualify_list([H0|T0], M, [H|T]) :-
|
|
qualify(H0, M, H),
|
|
qualify_list(T0, M, T).
|
|
|
|
qualify(M:Term, M, Term) :- !.
|
|
qualify(QTerm, _, QTerm).
|
|
|
|
|
|
option_clauses([], _, _, _) --> [].
|
|
option_clauses([H|T], Head, M, A) -->
|
|
option_clause(H, Head, M),
|
|
option_clauses(T, Head, M, A).
|
|
|
|
option_clause(Var, _, _) -->
|
|
{ var(Var), !,
|
|
throw(error(instantiation_error, _))
|
|
}.
|
|
option_clause(pass_to(PI0, Arg), Head, M) --> !,
|
|
{ canonical_pi(PI0, PI),
|
|
strip_module(M:PI, TM, Name/Arity),
|
|
functor(THead, Name, Arity),
|
|
Clause = ('$pred_option'(Head, pass_to(PI0, Arg), Opt, Seen) :-
|
|
\+ memberchk(PI-Arg, Seen),
|
|
predicate_options:pred_option(TM:THead, Opt, [PI-Arg|Seen]))
|
|
},
|
|
[ M:Clause ].
|
|
option_clause(Option, Head, M) -->
|
|
{ Option =.. [Name|ModeAndTypes], !,
|
|
modes_and_types(ModeAndTypes, Args, Body),
|
|
Opt =.. [Name|Args],
|
|
Clause = ('$pred_option'(Head, Option, Opt, _) :- Body)
|
|
},
|
|
[ M:Clause ].
|
|
option_clause(Option, _, _) -->
|
|
{ throw(error(type_error(option_specifier, Option)))
|
|
}.
|
|
|
|
modes_and_types([], [], true).
|
|
modes_and_types([H|T], [A|AT], Body) :-
|
|
mode_and_type(H, A, Body0),
|
|
( T == []
|
|
-> Body = Body0,
|
|
AT = []
|
|
; Body0 == true
|
|
-> modes_and_types(T, AT, Body)
|
|
; Body = (Body0,Body1),
|
|
modes_and_types(T, AT, Body1)
|
|
).
|
|
|
|
|
|
mode_and_type(-Type, A, (predicate_option_mode(output, A), Body)) :- !,
|
|
type_goal(Type, A, Body).
|
|
mode_and_type(+Type, A, Body) :- !,
|
|
type_goal(Type, A, Body).
|
|
mode_and_type(Type, A, Body) :-
|
|
type_goal(Type, A, Body).
|
|
|
|
type_goal(Type, A, predicate_option_type(Type, A)).
|
|
|
|
|
|
%% canonical_pi(+PIIn, -PIout)
|
|
|
|
canonical_pi(M:Name//Arity, M:Name/PArity) :-
|
|
integer(Arity), !,
|
|
PArity is Arity+2.
|
|
canonical_pi(Name//Arity, Name/PArity) :-
|
|
integer(Arity), !,
|
|
PArity is Arity+2.
|
|
canonical_pi(PI, PI).
|
|
|
|
|
|
/*******************************
|
|
* EXPAND *
|
|
*******************************/
|
|
|
|
%system:term_expansion((:- predicate_options(PI, Arg, Options)), Clauses) :-
|
|
% expand_predicate_options(PI, Arg, Options, Clauses).
|