1/* Part of SWI-Prolog 2 3 Author: Jan Wielemaker 4 E-mail: J.Wielemaker@vu.nl 5 WWW: http://www.swi-prolog.org 6 Copyright (c) 2011-2016, VU University Amsterdam 7 All rights reserved. 8 9 Redistribution and use in source and binary forms, with or without 10 modification, are permitted provided that the following conditions 11 are met: 12 13 1. Redistributions of source code must retain the above copyright 14 notice, this list of conditions and the following disclaimer. 15 16 2. Redistributions in binary form must reproduce the above copyright 17 notice, this list of conditions and the following disclaimer in 18 the documentation and/or other materials provided with the 19 distribution. 20 21 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 24 FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 25 COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 26 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 27 BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 28 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 29 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 31 ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 32 POSSIBILITY OF SUCH DAMAGE. 33*/ 34 35:- module(predicate_options, 36 [ predicate_options/3, % +PI, +Arg, +Options 37 assert_predicate_options/4, % +PI, +Arg, +Options, ?New 38 39 current_option_arg/2, % ?PI, ?Arg 40 current_predicate_option/3, % ?PI, ?Arg, ?Option 41 check_predicate_option/3, % +PI, +Arg, +Option 42 % Create declarations 43 current_predicate_options/3, % ?PI, ?Arg, ?Options 44 retractall_predicate_options/0, 45 derived_predicate_options/3, % :PI, ?Arg, ?Options 46 derived_predicate_options/1, % +Module 47 % Checking 48 check_predicate_options/0, 49 derive_predicate_options/0, 50 check_predicate_options/1 % :PredicateIndicator 51 ]). 52:- use_module(library(lists)). 53:- use_module(library(pairs)). 54:- use_module(library(error)). 55:- use_module(library(lists)). 56:- use_module(library(debug)). 57:- use_module(library(prolog_clause)). 58 59:- meta_predicate 60 predicate_options( , , ), 61 assert_predicate_options( , , , ), 62 current_predicate_option( , , ), 63 check_predicate_option( , , ), 64 current_predicate_options( , , ), 65 current_option_arg( , ), 66 pred_option( , ), 67 derived_predicate_options( , , ), 68 check_predicate_options( ).
134:- multifile option_decl/3, pred_option/3. 135:- dynamic dyn_option_decl/3.
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.
173predicate_options(PI, Arg, Options) :-
174 throw(error(context_error(nodirective,
175 predicate_options(PI, Arg, Options)), _)).
false
, the predicate becomes semidet and fails
without modifications if modifications are required.185assert_predicate_options(PI, Arg, Options, New) :- 186 canonical_pi(PI, M:Name/Arity), 187 functor(Head, Name, Arity), 188 ( dyn_option_decl(Head, M, Arg) 189 -> true 190 ; New = true, 191 assertz(dyn_option_decl(Head, M, Arg)) 192 ), 193 phrase('$predopts':option_clauses(Options, Head, M, Arg), 194 OptionClauses), 195 forall(member(Clause, OptionClauses), 196 assert_option_clause(Clause, New)), 197 ( var(New) 198 -> New = false 199 ; true 200 ). 201 202assert_option_clause(Clause, New) :- 203 rename_clause(Clause, NewClause, 204 '$pred_option'(A,B,C,D), '$dyn_pred_option'(A,B,C,D)), 205 clause_head(NewClause, NewHead), 206 ( clause(NewHead, _) 207 -> true 208 ; New = true, 209 assertz(NewClause) 210 ). 211 212clause_head(M:(Head:-_Body), M:Head) :- !. 213clause_head((M:Head :-_Body), M:Head) :- !. 214clause_head(Head, Head). 215 216rename_clause(M:Clause, M:NewClause, Head, NewHead) :- 217 !, 218 rename_clause(Clause, NewClause, Head, NewHead). 219rename_clause((Head :- Body), (NewHead :- Body), Head, NewHead) :- !. 220rename_clause(Head, NewHead, Head, NewHead) :- !. 221rename_clause(Head, Head, _, _). 222 223 224 225 /******************************* 226 * QUERY OPTIONS * 227 *******************************/
234current_option_arg(Module:Name/Arity, Arg) :- 235 current_option_arg(Module:Name/Arity, Arg, _DefM). 236 237current_option_arg(Module:Name/Arity, Arg, DefM) :- 238 atom(Name), integer(Arity), 239 !, 240 resolve_module(Module:Name/Arity, DefM:Name/Arity), 241 functor(Head, Name, Arity), 242 ( option_decl(Head, DefM, Arg) 243 ; dyn_option_decl(Head, DefM, Arg) 244 ). 245current_option_arg(M:Name/Arity, Arg, M) :- 246 ( option_decl(Head, M, Arg) 247 ; dyn_option_decl(Head, M, Arg) 248 ), 249 functor(Head, Name, Arity).
?- 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.
266current_predicate_option(Module:PI, Arg, Option) :-
267 current_option_arg(Module:PI, Arg, DefM),
268 PI = Name/Arity,
269 functor(Head, Name, Arity),
270 catch(pred_option(DefM:Head, Option),
271 error(type_error(_,_),_),
272 fail).
285check_predicate_option(Module:PI, Arg, Option) :- 286 define_predicate(Module:PI), 287 current_option_arg(Module:PI, Arg, DefM), 288 PI = Name/Arity, 289 functor(Head, Name, Arity), 290 ( pred_option(DefM:Head, Option) 291 -> true 292 ; existence_error(option, Option) 293 ). 294 295 296pred_option(M:Head, Option) :- 297 pred_option(M:Head, Option, []). 298 299pred_option(M:Head, Option, Seen) :- 300 ( has_static_option_decl(M), 301 M:'$pred_option'(Head, _, Option, Seen) 302 ; has_dynamic_option_decl(M), 303 M:'$dyn_pred_option'(Head, _, Option, Seen) 304 ). 305 306has_static_option_decl(M) :- 307 '$c_current_predicate'(_, M:'$pred_option'(_,_,_,_)). 308has_dynamic_option_decl(M) :- 309 '$c_current_predicate'(_, M:'$dyn_pred_option'(_,_,_,_)). 310 311 312 /******************************* 313 * TYPE&MODE CONSTRAINTS * 314 *******************************/ 315 316:- public 317 system:predicate_option_mode/2, 318 system:predicate_option_type/2. 319 320add_attr(Var, Value) :- 321 ( get_attr(Var, predicate_options, Old) 322 -> put_attr(Var, predicate_options, [Value|Old]) 323 ; put_attr(Var, predicate_options, [Value]) 324 ). 325 326systempredicate_option_type(Type, Arg) :- 327 var(Arg), 328 !, 329 add_attr(Arg, option_type(Type)). 330systempredicate_option_type(Type, Arg) :- 331 must_be(Type, Arg). 332 333systempredicate_option_mode(Mode, Arg) :- 334 var(Arg), 335 !, 336 add_attr(Arg, option_mode(Mode)). 337systempredicate_option_mode(Mode, Arg) :- 338 check_mode(Mode, Arg). 339 340check_mode(input, Arg) :- 341 ( nonvar(Arg) 342 -> true 343 ; instantiation_error(Arg) 344 ). 345check_mode(output, Arg) :- 346 ( var(Arg) 347 -> true 348 ; uninstantiation_error(Arg) 349 ). 350 351attr_unify_hook([], _). 352attr_unify_hook([H|T], Var) :- 353 option_hook(H, Var), 354 attr_unify_hook(T, Var). 355 356option_hook(option_type(Type), Value) :- 357 is_of_type(Type, Value). 358option_hook(option_mode(Mode), Value) :- 359 check_mode(Mode, Value). 360 361 362attribute_goals(Var) --> 363 { get_attr(Var, predicate_options, Attrs) }, 364 option_goals(Attrs, Var). 365 366option_goals([], _) --> []. 367option_goals([H|T], Var) --> 368 option_goal(H, Var), 369 option_goals(T, Var). 370 371option_goal(option_type(Type), Var) --> [predicate_option_type(Type, Var)]. 372option_goal(option_mode(Mode), Var) --> [predicate_option_mode(Mode, Var)]. 373 374 375 /******************************* 376 * OUTPUT DECLARATIONS * 377 *******************************/
387current_predicate_options(PI, Arg, Options) :- 388 define_predicate(PI), 389 setof(Arg-Option, 390 current_predicate_option_decl(PI, Arg, Option), 391 Options0), 392 group_pairs_by_key(Options0, Grouped), 393 member(Arg-Options, Grouped). 394 395current_predicate_option_decl(PI, Arg, Option) :- 396 current_predicate_option(PI, Arg, Option0), 397 Option0 =.. [Name|Values], 398 maplist(mode_and_type, Values, Types), 399 Option =.. [Name|Types]. 400 401mode_and_type(Value, ModeAndType) :- 402 copy_term(Value,_,Goals), 403 ( memberchk(predicate_option_mode(output, _), Goals) 404 -> ModeAndType = -(Type) 405 ; ModeAndType = Type 406 ), 407 ( memberchk(predicate_option_type(Type, _), Goals) 408 -> true 409 ; Type = any 410 ). 411 412define_predicate(PI) :- 413 ground(PI), 414 !, 415 PI = M:Name/Arity, 416 functor(Head, Name, Arity), 417 once(predicate_property(M:Head, _)). 418define_predicate(_).
426derived_predicate_options(PI, Arg, Options) :- 427 define_predicate(PI), 428 setof(Arg-Option, 429 derived_predicate_option(PI, Arg, Option), 430 Options0), 431 group_pairs_by_key(Options0, Grouped), 432 member(Arg-Options1, Grouped), 433 PI = M:_, 434 phrase(expand_pass_to_options(Options1, M), Options2), 435 sort(Options2, Options). 436 437derived_predicate_option(PI, Arg, Decl) :- 438 current_option_arg(PI, Arg, DefM), 439 PI = _:Name/Arity, 440 functor(Head, Name, Arity), 441 has_dynamic_option_decl(DefM), 442 ( has_static_option_decl(DefM), 443 DefM:'$pred_option'(Head, Decl, _, []) 444 ; DefM:'$dyn_pred_option'(Head, Decl, _, []) 445 ).
pass_to(PI,Arg)
if PI does not refer to a
public predicate.452expand_pass_to_options([], _) --> []. 453expand_pass_to_options([H|T], M) --> 454 expand_pass_to(H, M), 455 expand_pass_to_options(T, M). 456 457expand_pass_to(pass_to(PI, Arg), Module) --> 458 { strip_module(Module:PI, M, Name/Arity), 459 functor(Head, Name, Arity), 460 \+ ( predicate_property(M:Head, exported) 461 ; predicate_property(M:Head, public) 462 ; M == system 463 ), 464 !, 465 current_predicate_options(M:Name/Arity, Arg, Options) 466 }, 467 list(Options). 468expand_pass_to(Option, _) --> 469 [Option]. 470 471list([]) --> []. 472list([H|T]) --> [H], list(T).
current_output
stream.479derived_predicate_options(Module) :- 480 var(Module), 481 !, 482 forall(current_module(Module), 483 derived_predicate_options(Module)). 484derived_predicate_options(Module) :- 485 findall(predicate_options(Module:PI, Arg, Options), 486 ( derived_predicate_options(Module:PI, Arg, Options), 487 PI = Name/Arity, 488 functor(Head, Name, Arity), 489 ( predicate_property(Module:Head, exported) 490 -> true 491 ; predicate_property(Module:Head, public) 492 ) 493 ), 494 Decls0), 495 maplist(qualify_decl(Module), Decls0, Decls1), 496 sort(Decls1, Decls), 497 ( Decls \== [] 498 -> format('~N~n~n% Predicate option declarations for module ~q~n~n', 499 [Module]), 500 forall(member(Decl, Decls), 501 portray_clause((:-Decl))) 502 ; true 503 ). 504 505qualify_decl(M, 506 predicate_options(PI0, Arg, Options0), 507 predicate_options(PI1, Arg, Options1)) :- 508 qualify(PI0, M, PI1), 509 maplist(qualify_option(M), Options0, Options1). 510 511qualify_option(M, pass_to(PI0, Arg), pass_to(PI1, Arg)) :- 512 !, 513 qualify(PI0, M, PI1). 514qualify_option(_, Opt, Opt). 515 516qualify(M:Term, M, Term) :- !. 517qualify(QTerm, _, QTerm). 518 519 520 /******************************* 521 * CLEANUP * 522 *******************************/
528retractall_predicate_options :- 529 forall(retract(dyn_option_decl(_,M,_)), 530 abolish(M:'$dyn_pred_option'/4)). 531 532 533 /******************************* 534 * COMPILE-TIME CHECKER * 535 *******************************/ 536 537 538:- thread_local 539 new_decl/1.
555check_predicate_options :-
556 forall(current_module(Module),
557 check_predicate_options_module(Module)).
library(option)
or passes
options to other predicates that are known to process options.
The process is repeated until no new declarations are retrieved.
569derive_predicate_options :- 570 derive_predicate_options(NewDecls), 571 ( NewDecls == [] 572 -> true 573 ; print_message(informational, check_options(new(NewDecls))), 574 new_decls(NewDecls), 575 derive_predicate_options 576 ). 577 578new_decls([]). 579new_decls([predicate_options(PI, A, O)|T]) :- 580 assert_predicate_options(PI, A, O, _), 581 new_decls(T). 582 583 584derive_predicate_options(NewDecls) :- 585 call_cleanup( 586 ( forall( 587 current_module(Module), 588 forall( 589 ( predicate_in_module(Module, PI), 590 PI = Name/Arity, 591 functor(Head, Name, Arity), 592 catch(Module:clause(, Body, Ref), _, fail) 593 ), 594 check_clause((Head:-Body), Module, Ref, decl))), 595 ( setof(Decl, retract(new_decl(Decl)), NewDecls) 596 -> true 597 ; NewDecls = [] 598 ) 599 ), 600 retractall(new_decl(_))). 601 602 603check_predicate_options_module(Module) :- 604 forall(predicate_in_module(Module, PI), 605 check_predicate_options(Module:PI)). 606 607predicate_in_module(Module, PI) :- 608 current_predicate(Module:PI), 609 PI = Name/Arity, 610 functor(Head, Name, Arity), 611 \+ predicate_property(Module:Head, imported_from(_)).
618check_predicate_options(Module:Name/Arity) :-
619 debug(predicate_options, 'Checking ~q', [Module:Name/Arity]),
620 functor(Head, Name, Arity),
621 forall(catch(Module:clause(, Body, Ref), _, fail),
622 check_clause((Head:-Body), Module, Ref, check)).
633check_clause((Head:-Body), M, ClauseRef, Action) :-
634 !,
635 catch(check_body(Body, M, _, Action), E, true),
636 ( var(E)
637 -> option_decl(M:Head, Action)
638 ; ( clause_info(ClauseRef, File, TermPos, _NameOffset),
639 TermPos = term_position(_,_,_,_,[_,BodyPos]),
640 catch(check_body(Body, M, BodyPos, Action),
641 error(Formal, ArgPos), true),
642 compound(ArgPos),
643 arg(1, ArgPos, CharCount),
644 integer(CharCount)
645 -> Location = file_char_count(File, CharCount)
646 ; Location = clause(ClauseRef),
647 E = error(Formal, _)
648 ),
649 print_message(error, predicate_option_error(Formal, Location))
650 ).
655:- multifile 656 prolog:called_by/4, % +Goal, +Module, +Context, -Called 657 prolog:called_by/2. % +Goal, -Called 658 659check_body(Var, _, _, _) :- 660 var(Var), 661 !. 662check_body(M:G, _, term_position(_,_,_,_,[_,Pos]), Action) :- 663 !, 664 check_body(G, M, Pos, Action). 665check_body((A,B), M, term_position(_,_,_,_,[PA,PB]), Action) :- 666 !, 667 check_body(A, M, PA, Action), 668 check_body(B, M, PB, Action). 669check_body(A=B, _, _, _) :- % partial evaluation 670 unify_with_occurs_check(A,B), 671 !. 672check_body(Goal, M, term_position(_,_,_,_,ArgPosList), Action) :- 673 callable(Goal), 674 functor(Goal, Name, Arity), 675 ( '$get_predicate_attribute'(M:Goal, imported, DefM) 676 -> true 677 ; DefM = M 678 ), 679 ( eval_option_pred(DefM:Goal) 680 -> true 681 ; current_option_arg(DefM:Name/Arity, OptArg), 682 !, 683 arg(OptArg, Goal, Options), 684 nth1(OptArg, ArgPosList, ArgPos), 685 check_options(DefM:Name/Arity, OptArg, Options, ArgPos, Action) 686 ). 687check_body(Goal, M, _, Action) :- 688 ( ( predicate_property(M:Goal, imported_from(IM)) 689 -> true 690 ; IM = M 691 ), 692 prolog:called_by(Goal, IM, M, Called) 693 ; prolog:called_by(Goal, Called) 694 ), 695 !, 696 check_called_by(Called, M, Action). 697check_body(Meta, M, term_position(_,_,_,_,ArgPosList), Action) :- 698 '$get_predicate_attribute'(M:Meta, meta_predicate, Head), 699 !, 700 check_meta_args(1, Head, Meta, M, ArgPosList, Action). 701check_body(_, _, _, _). 702 703check_meta_args(I, Head, Meta, M, [ArgPos|ArgPosList], Action) :- 704 arg(I, Head, AS), 705 !, 706 ( AS == 0 707 -> arg(I, Meta, MA), 708 check_body(MA, M, ArgPos, Action) 709 ; true 710 ), 711 succ(I, I2), 712 check_meta_args(I2, Head, Meta, M, ArgPosList, Action). 713check_meta_args(_,_,_,_, _, _).
719check_called_by([], _, _). 720check_called_by([H|T], M, Action) :- 721 ( H = G+N 722 -> ( extend(G, N, G2) 723 -> check_body(G2, M, _, Action) 724 ; true 725 ) 726 ; check_body(H, M, _, Action) 727 ), 728 check_called_by(T, M, Action). 729 730extend(Goal, N, GoalEx) :- 731 callable(Goal), 732 Goal =.. List, 733 length(Extra, N), 734 append(List, Extra, ListEx), 735 GoalEx =.. ListEx.
pass_to(PI, OptArg)
.745check_options(PI, OptArg, QOptions, ArgPos, Action) :- 746 debug(predicate_options, '\tChecking call to ~q', [PI]), 747 remove_qualifier(QOptions, Options), 748 must_be(list_or_partial_list, Options), 749 check_option_list(Options, PI, OptArg, Options, ArgPos, Action). 750 751remove_qualifier(X, X) :- 752 var(X), 753 !. 754remove_qualifier(_:X, X) :- !. 755remove_qualifier(X, X). 756 757check_option_list(Var, PI, OptArg, _, _, _) :- 758 var(Var), 759 !, 760 annotate(Var, pass_to(PI, OptArg)). 761check_option_list([], _, _, _, _, _). 762check_option_list([H|T], PI, OptArg, Options, ArgPos, Action) :- 763 check_option(PI, OptArg, H, ArgPos, Action), 764 check_option_list(T, PI, OptArg, Options, ArgPos, Action). 765 766check_option(_, _, _, _, decl) :- !. 767check_option(PI, OptArg, Opt, ArgPos, _) :- 768 catch(check_predicate_option(PI, OptArg, Opt), E, true), 769 !, 770 ( var(E) 771 -> true 772 ; E = error(Formal,_), 773 throw(error(Formal,ArgPos)) 774 ). 775 776 777 /******************************* 778 * ANNOTATIONS * 779 *******************************/
786annotate(Var, Term) :- 787 ( get_attr(Var, predopts_analysis, Old) 788 -> put_attr(Var, predopts_analysis, [Term|Old]) 789 ; var(Var) 790 -> put_attr(Var, predopts_analysis, [Term]) 791 ; true 792 ). 793 794annotations(Var, Annotations) :- 795 get_attr(Var, predopts_analysis, Annotations). 796 797predopts_analysisattr_unify_hook(Opts, Value) :- 798 get_attr(Value, predopts_analysis, Others), 799 !, 800 append(Opts, Others, All), 801 put_attr(Value, predopts_analysis, All). 802predopts_analysisattr_unify_hook(_, _). 803 804 805 /******************************* 806 * PARTIAL EVAL * 807 *******************************/ 808 809eval_option_pred(swi_option:option(Opt, Options)) :- 810 processes(Opt, Spec), 811 annotate(Options, Spec). 812eval_option_pred(swi_option:option(Opt, Options, _Default)) :- 813 processes(Opt, Spec), 814 annotate(Options, Spec). 815eval_option_pred(swi_option:select_option(Opt, Options, Rest)) :- 816 ignore(unify_with_occurs_check(Rest, Options)), 817 processes(Opt, Spec), 818 annotate(Options, Spec). 819eval_option_pred(swi_option:select_option(Opt, Options, Rest, _Default)) :- 820 ignore(unify_with_occurs_check(Rest, Options)), 821 processes(Opt, Spec), 822 annotate(Options, Spec). 823eval_option_pred(swi_option:meta_options(_Cond, QOptionsIn, QOptionsOut)) :- 824 remove_qualifier(QOptionsIn, OptionsIn), 825 remove_qualifier(QOptionsOut, OptionsOut), 826 ignore(unify_with_occurs_check(OptionsIn, OptionsOut)). 827 828processes(Opt, Spec) :- 829 compound(Opt), 830 functor(Opt, OptName, 1), 831 Spec =.. [OptName,any]. 832 833 834 /******************************* 835 * NEW DECLARTIONS * 836 *******************************/
847option_decl(_, check) :- !. 848option_decl(M:_, _) :- 849 system_module(M), 850 !. 851option_decl(M:_, _) :- 852 has_static_option_decl(M), 853 !. 854option_decl(M:Head, _) :- 855 compound(Head), 856 arg(AP, Head, QA), 857 remove_qualifier(QA, A), 858 annotations(A, Annotations0), 859 functor(Head, Name, Arity), 860 PI = M:Name/Arity, 861 delete(Annotations0, pass_to(PI,AP), Annotations), 862 Annotations \== [], 863 Decl = predicate_options(PI, AP, Annotations), 864 ( new_decl(Decl) 865 -> true 866 ; assert_predicate_options(M:Name/Arity, AP, Annotations, false) 867 -> true 868 ; assertz(new_decl(Decl)), 869 debug(predicate_options(decl), '~q', [Decl]) 870 ), 871 fail. 872option_decl(_, _). 873 874system_module(system) :- !. 875system_module(Module) :- 876 sub_atom(Module, 0, _, _, $). 877 878 879 /******************************* 880 * MISC * 881 *******************************/ 882 883canonical_pi(M:Name//Arity, M:Name/PArity) :- 884 integer(Arity), 885 PArity is Arity+2. 886canonical_pi(PI, PI).
896resolve_module(Module:Name/Arity, DefM:Name/Arity) :- 897 functor(Head, Name, Arity), 898 ( '$get_predicate_attribute'(Module:Head, imported, M) 899 -> DefM = M 900 ; DefM = Module 901 ). 902 903 904 /******************************* 905 * MESSAGES * 906 *******************************/ 907:- multifile 908 prolog:message//1. 909 910prologmessage(predicate_option_error(Formal, Location)) --> 911 error_location(Location), 912 '$messages':term_message(Formal). % TBD: clean interface 913prologmessage(check_options(new(Decls))) --> 914 [ 'Inferred declarations:'-[], nl ], 915 new_decls(Decls). 916 917error_location(file_char_count(File, CharPos)) --> 918 { filepos_line(File, CharPos, Line, LinePos) }, 919 [ '~w:~d:~d: '-[File, Line, LinePos] ]. 920error_location(clause(ClauseRef)) --> 921 { clause_property(ClauseRef, file(File)), 922 clause_property(ClauseRef, line_count(Line)) 923 }, 924 !, 925 [ '~w:~d: '-[File, Line] ]. 926error_location(clause(ClauseRef)) --> 927 [ 'Clause ~q: '-[ClauseRef] ]. 928 929filepos_line(File, CharPos, Line, LinePos) :- 930 setup_call_cleanup( 931 ( open(File, read, In), 932 open_null_stream(Out) 933 ), 934 ( Skip is CharPos-1, 935 copy_stream_data(In, Out, Skip), 936 stream_property(In, position(Pos)), 937 stream_position_data(line_count, Pos, Line), 938 stream_position_data(line_position, Pos, LinePos) 939 ), 940 ( close(Out), 941 close(In) 942 )). 943 944new_decls([]) --> []. 945new_decls([H|T]) --> 946 [ ' :- ~q'-[H], nl ], 947 new_decls(T). 948 949 950 /******************************* 951 * SYSTEM DECLARATIONS * 952 *******************************/ 953 954:- use_module(library(dialect/swi/syspred_options)).
Access and analyse predicate options
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 valuestext
andbinary
. 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.
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.library(option)
for accessing options in Prolog code. */