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).
 |