1/***************************************************************************** 2 * This file is part of the Prolog Development Tool (PDT) 3 * 4 * Author: G�nter Kniesel (among others) 5 * WWW: http://sewiki.iai.uni-bonn.de/research/pdt/start 6 * Mail: pdt@lists.iai.uni-bonn.de 7 * Copyright (C): 2004-2012, CS Dept. III, University of Bonn 8 * 9 * All rights reserved. This program is made available under the terms 10 * of the Eclipse Public License v1.0 which accompanies this distribution, 11 * and is available at http://www.eclipse.org/legal/epl-v10.html 12 * 13 ****************************************************************************/ 14 15% Date: 25.06.2006 16 17/* 18 * This file contains predicates for locating definitions (declarations and 19 * clauses) in SWI-Prolog modules and testing visibility of predicates in 20 * modules. 21 * 22 * Used in pdt/pl/{pdt_search,pdt_xref}.pl and in 23 * ** pdt.runtime.builder/prolog-src/analyzer/metafile_referencer.pl 24 */ 25:- module( utils4modules_visibility, 26 [ 27 module_of_file/2, % File, Module 28<<<<<<< HEAD 29 defined_in_files/4, % Module, Name, Arity, Locations 30 defined_in_file/6, % Module, Name, Arity, Nth,File,StartingLine ** 31 declared_in_file/4, % Module, Name, Arity, Location=[File-[Line]] -- 32 33 hidden_name/1, % (Name) 34 35 defined_in/3, % Module, Name, Arity 36 defined_in/4, % Module, Name, Arity, DefiningModule 37 visible_in/3, % Module, Name, Arity 38 undefined_in/3 % Module, Name, Arity 39 ] ). 40 41 42 43%% module_of_file(?File,?Module) 44% 45% Module is the module defined in File. 46% If the file defines no explicit module or the 47% defined module is a hidden system module (whose 48% name starts with $) the Module is either 'user' 49% . 50module_of_file(File,Module):- 51 module_property(Module,file(File)), % SWI: Fails if File defines no module 52 % or if it defines a hidden module. 53 % Nondeterministic for mode (-,-). 54======= 55 56 empty_module/1, % (Module) hidden_module/1, % Module visible_in_module/3, % Module, Name, Arity declared_in_module/2, % Module, Head declared_in_module/3, % Module, Head, DeclaringModule (not generating) declared_in_module/4, % Module, Name, Arity, DeclaringModule referenced_but_undeclared/3, % Module, Name, Arity declared_but_undefined/3, % Module, Name, Arity defined_in_module/2, % Module, Head defined_in_module/3, % Module, Name, Arity defined_in_module/4, % Module, Name, Arity, DefiningModule defined_in_files/4, % Module, Name, Arity, Locations defined_in_file/6, % Module, Name, Arity, Nth,File,StartingLine declared_in_file/4 % Module, Name, Arity, Location=[File-[Line]] ] ).
78hidden_module(M) :- starts_with_dollar(M). 79 80starts_with_dollar(Atom) :- sub_atom( Atom, 0, 1, _, '$').
87empty_module(Module) :- 88 ( var(Module) % generating mode 89 -> ( setof( M, empty_module__(M), Set),% avoid multiply returning 90 member(Module,Set) % ... the same module 91 ) 92 ; empty_module__(Module), ! % checking mode 93 ). 94 95% A module is empty if all its predicates are imported 96% (put differently: none of its predicates is not imported). 97empty_module__(M) :- % generator skips system Modules :-( 98 current_predicate(M:_/_), 99 \+ ( current_predicate(M:N/A), 100 functor(H,N,A), 101 \+ predicate_property(M:H, imported_from(_)) 102 ).
110module_of_file(File,Module):- 111 module_property(Module,file(File)). % Fails if File defines no module 112 % or if it defines a hidden module 113 % whose name starts with $ 114>>>>>>> 92defde0ffaad6ef7bd1d65d2c68e72011c7c32c 115module_of_file(File,Module):- 116 atom(File), % If File is provided as input 117 \+ module_property(Module,file(File)), % and there is no module in that file 118 ( Module=user % the default module is 'user' 119 ; Module=system % but it could also be 'system' 120 ). 121 122<<<<<<< HEAD 123module_of_file_including_system(File,Module) :- % mode(?,?) 124 module_property(Module,file(File)). % Fails if File defines no module 125 % or if it defines a hidden module 126 % whose name starts with $ 127 128module_of_file_including_system(File,M):- % mode(?,?) 129 current_module_including_system(M), 130 setof( F, file_of_module(M,F), Files ), 131 member(File,Files). 132 133 134current_module_including_system(M) :- 135 setof( M, N^A^defined_in(M,N,A), AllModules), 136 member(M, AllModules). 137 138file_of_module(M,File) :- 139 defined_in(M,N,A), 140 functor(P,N,A), 141 predicate_property(M:P,file(File)). 142======= 143%% visible_in_module(?Module,?Name,?Arity) is nondet. 144% 145% Suceed if the predicate Name/Arity is visible in Module 146% either via a local declaration or import. 147% 148% The used predicate_property(Head,visible) is documented as: 149% True when predicate can be called without raising a predicate 150% existence error. This means that the predicate is (1) 151% defined, (2) can be inherited from one of the default modules 152% (see default_module/2) or (3) can be autoloaded. The behaviour 153% is logically consistent iff the propery visible is provided 154% explicitly. If the property is left unbound, only defined 155% predicates are enumerated. 156 157visible_in_module(Module,Name,Arity) :- 158% (ground(functor(Head,Name,Arity), 159% predicate_property(Module:Head,visible). 160% The above was created by Jan Wielemaker during his visit to our group 161% in Nov. 2011. It is intended as a better behaved alternative to the 162% strangely inconsistent versions of current_predicate/1 and /2. 163 164 current_predicate(Module:Name/Arity). 165% 166% <-- Beware of current_predicate/2: It hides system modules! 167% Only current_predicate/1 returns ALL modules that see Name/Arity, 168% including (hidden) system modules, such as '$syspreds'. 169% BUT it does it only if Name AND Arity are instantiated. 170% If only Name is instantiated, current_predicate/1 only returns 171% non-system modules that actually CALL Name/_. 172 173/* 174Inconsistent behaviour of current_predicate(M:F/N): 175 1763 ?- F=visible,current_predicate(M:F/N). 177F = visible, 178M = system, 179N = 1 ; 180 181F = visible, 182M = gui_tracer, 183N = 1 ; 184 185false. 186 1874 ?- F=visible,M='$syspreds', current_predicate(M:F/N). 188M = '$syspreds', 189F = visible, 190N = 1 ; 191 192false. 193 1945 ?- F=visible,N=1,findall(M:F/N, current_predicate(M:F/N), All), length(All,L). 195F = visible, 196N = 1, 197All = [emacs_buffer:visible/1, pce_hyper:visible/1, make:visible/1, 'condor.depend.expand.dnf':visible/1, targetModule:visible/1, prolog_break:visible/1, 198utils4modules:visible/1, emacs_fundamental_mode:... / ..., ... : ...|...], 199L = 203. 200*/
declared_in_module(+Module, +Head)
is det.
declared_in_module(+Module, ?Head) is nondet.
declared_in_module(?Module, ?Head) is nondet.
Determine whether the predicate indicated by Head has a local (non-imported) declaration in the module Module. The predicate succeeds if there is at least a declaration (but possibly no single clause) of the predicate in the module. If you want it to fail you must abolish the predicate declaration, not just retract all its clauses. See the built-ins Prolog predicates abolish/1, abolish/1, retractall/1, retract/1
216declared_in_module(Module, Head) :- 217 ( true ; Module = '$syspreds'), % Try also hidden module 218 current_predicate(_, Module:Head), % Head is declared 219 \+ predicate_property(Module:Head, imported_from(_)). % but not imported
232declared_in_module(Module,Name,Arity,DeclaringModule) :-
233 visible_in_module(Module,Name,Arity), % Name/arity is visible in Module
234 functor(Head,Name,Arity),
235 ( predicate_property(Module:Head, imported_from(M)) % by being imported
236 -> DeclaringModule = M
237 ; DeclaringModule = Module % by being declared locally
238 ).
declared_in_module(Module,Name,Arity,DeclaringModule)
,
functor(Head,Name,Arity)
this call does not generate, it assumes Head is instantiated!248declared_in_module(Module,Head,DeclaringModule) :- 249 ( predicate_property(Module:Head, imported_from(M)) % imported 250 -> DeclaringModule = M 251 ; DeclaringModule = Module % declared locally 252 ), 253 functor(Head,Name,Arity), 254 visible_in_module(Module,Name,Arity). % Name/arity is visible in Module
clause(es)
in the module can come from different files
(because of multifile predicates).
263defined_in_module(Module,Head) :-
264 functor(Head,Name,Arity),
265 defined_in_module(Module,Name,Arity).
clause(es)
in the module can come from different files
(because of multifile predicates).
274defined_in_module(Module,Name,Arity) :- % <<< deleted 1 argument
275 defined_in_module(Module,Name,Arity,Module).
clause(es)
in DefiningModule can come from different files
(because of multifile predicates).
284defined_in_module(ReferencedModule,Name,Arity,DefiningModule) :-
285 declared_in_module(ReferencedModule,Name,Arity,DefiningModule),
286 functor(Head,Name,Arity),
287 \+ predicate_property(DefiningModule:Head, imported(_)).
291list_module(Module) :-
292 nonvar(Module),
293 forall( defined_in_module(Module,F,A), listing(Module:F/A) ).
299declared_but_undefined(Module,Name,Arity) :- % <<< deleted 1 argument
300 declared_in_module(Module,Name,Arity,Module),
301 functor(Head,Name,Arity),
302 \+ (predicate_property(Module:Head, number_of_clauses(X)), X>0).
310referenced_but_undeclared(Module,Name,Arity) :-
311 predicate_property(Module:Head,undefined),
312 functor(Head,Name,Arity).
Get the source locations (File and Line) of all clauses that define Module:Name/Arity.
320defined_in_file(Module,Name,Arity, N,File,Line) :- 321 defined_in_file(Module,Name,Arity, _Ref, N,File,Line). 322 323defined_in_file(Module,Name,Arity, Ref, N,File,Line) :- 324 declared_in_module(Module,Name,Arity,Module), 325 functor(Head,Name,Arity), 326 nth_clause(Module:Head,N,Ref), 327 clause_property(Ref,file(File)), 328 clause_property(Ref,line_count(Line)). 329 330>>>>>>> 92defde0ffaad6ef7bd1d65d2c68e72011c7c32c 331 332%% declared_in_file(?Module, Head, ?File, ?Line) is nondet 333% 334% File is the file containing the declaration for the predicate Head, 335% which is visible in Module. 336% Line = 1 (approximating the line number information missing for declarations). 337 338<<<<<<< HEAD 339declared_in_file(Module,Name,Arity,[File-Lines]) :- 340 functor(Head,Name,Arity), 341 predicate_property(Module:Head,foreign), 342 !, 343 File=none, 344 Lines=none. 345% File = 'No Prolog source code (only compiled external language code)', 346% Line = 0. 347======= 348declared_in_file(Module,Name,Arity,[File-[Line]]) :- 349 functor(Head,Name,Arity), 350 predicate_property(Module:Head,foreign), 351 !, 352 File = 'No Prolog source code (only compiled external language code)', 353 Line = 0. 354>>>>>>> 92defde0ffaad6ef7bd1d65d2c68e72011c7c32c 355declared_in_file(Module,_Name,_Arity,[File-[Line]]) :- 356 module_property(Module, file(File)), % declaration in known file 357 !, 358 Line=1. % guess the unknown line nr 359<<<<<<< HEAD 360declared_in_file(Module,Name,Arity,[File-Lines]) :- 361 functor(Head,Name,Arity), 362 predicate_property(Module:Head,dynamic), 363 !, 364 File=none, 365 Lines=none. 366% File = 'Dynamic predicate, no Prolog source code (only dynamic code)' , 367% Line = 0. 368======= 369declared_in_file(Module,Name,Arity,[File-[Line]]) :- 370 functor(Head,Name,Arity), 371 predicate_property(Module:Head,foreign), 372 File = 'Dynamic predicate, no Prolog source code (only dynamic code)' , 373 Line = 0. 374>>>>>>> 92defde0ffaad6ef7bd1d65d2c68e72011c7c32c 375 376%% 377% declared_or_defined_in_files(+Module,+Name,+Arity, Locations) is semidet 378% 379% Locations is a list of File-Lines terms whose Lines 380% is a list of numbers indicating the starting lines of 381% the clauses for Module:Name/Arity contained in File. 382defined_in_files(Module,Name,Arity,Locations) :- 383 ( var(Module) 384 ; var(Name) 385 ; var(Arity) 386 ), 387 throw( input_argument_free(defined_in_files(Module,Name,Arity,Locations)) ). 388 389defined_in_files(Module,Name,Arity,Locations) :- 390 findall( File-Lines, 391 setof( Line, Module^Name^Arity^N^ 392 defined_in_file(Module,Name,Arity, N,File,Line), 393 Lines 394 ), 395 SrcLocations 396 ), 397 ( SrcLocations == [] 398<<<<<<< HEAD 399 -> ( defined_in(Module,Name,Arity,DeclaringModule), 400======= 401 -> ( declared_in_module(Module,Name,Arity,DeclaringModule), 402>>>>>>> 92defde0ffaad6ef7bd1d65d2c68e72011c7c32c 403 declared_in_file(DeclaringModule,Name,Arity,DeclLocation), 404 Locations = DeclLocation 405 ) 406 ; Locations = SrcLocations 407 ). 408 409<<<<<<< HEAD 410%% defined_in_file(-Module,-Name,-Arity,-N,?File,?Line) is nondet 411% defined_in_file(+Module,+Name,+Arity,+N,?File,?Line) is det 412% 413% The N-th clause of the predicate Module:Name/Arity starts at 414% line Line in File. 415% 416% @param File The full path of the file containing the N-th clause 417 418defined_in_file(Module,Name,Arity, N,File,Line) :- 419 defined_in(Module,Name,Arity,Module), 420 functor(Head,Name,Arity), 421 nth_clause(Module:Head,N,Ref), 422 clause_property(Ref,file(File)), 423 clause_property(Ref,line_count(Line)). 424% ( module_property(M, file(F)) 425% -> DDDeclaringModule=M 426% ; DDDeclaringModule=unknown 427% ). 428 429 430 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 431 % 432 % UNDEFINED, DEFINED, IMPLEMENTED, IMPORTED, VISIBLE % 433 % 434 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
declared_in_module(+Module, +Head)
is det.
declared_in_module(+Module, ?Head) is nondet.
declared_in_module(?Module, ?Head) is nondet.
Determine whether the predicate indicated by Head has a local (non-imported) declaration in the module Module. The predicate succeeds if there is at least a declaration (but possibly no single clause) of the predicate in the module.
446declared_in_module(Module, Head) :- 447 defined_in(Module, Head). 448 449defined_in(Module, Head) :- 450 ( nonvar(Head) 451 -> ( functor(Head,Name,Arity), defined_in(Module,Name,Arity) ) 452 ; ( defined_in(Module,Name,Arity), functor(Head,Name,Arity) ) 453 ).
466defined_in(Module,Name,Arity) :- 467 defined_in(SubModule,Name,Arity,Module), 468 ( % Non-hidden module does not import from any other 469 SubModule == Module 470 ; % "system" imports from hidden system modules 471 system == SubModule, 472 system \== Module, 473 hidden_name(Module) 474 ). 475 476 477% In SWI-Prolog names of hidden modules and predicates start with a $ sign: Name) (:- sub_atom(Name, 0, _, _, $).
491defined_in(Module,Name,Arity,DeclaringModule) :- 492 visible_in(Module,Name,Arity), % Name/arity is visible in Module 493 functor(Head,Name,Arity), 494 ( predicate_property(Module:Head, imported_from(M)) % by being imported 495 -> DeclaringModule = M 496 ; DeclaringModule = Module % by being declared locally 497 ). 498 499ddd(Module,Name,Arity) :- 500 visible_in(Module,Name,Arity), % Name/arity is visible in Module 501 functor(Head,Name,Arity), 502 \+ predicate_property(Module:Head, imported_from(_)). 503 504definition_category(Module,Name,Arity,Category) :- 505 defined_in(Module,Name,Arity), 506 functor(Head,Name,Arity), 507 ( predicate_property(Module:Head, foreign) 508 -> Category = foreign 509 ; ( predicate_property(Module:Head, number_of_clauses(0)) 510 -> Category = declared 511 ; Category = implemented 512 ) 513 ).
522implemented_in(Module,Name,Arity) :- % <<< deleted 1 argument
523 clause_location(Module,Name,Arity,_N,_File,_Line).
531undefined_in(Module,Name,Arity) :-
532 (atom(Name), integer(Arity))
533 -> % Checking mode
534 ( functor(Head,Name,Arity),
535 predicate_property(Module:Head,undefined)
536 )
537 ; % Generating mode
538 ( predicate_property(Module:Head,undefined),
539 functor(Head,Name,Arity)
540 ) .
550visible_in(Module,Name,Arity) :- 551 current_predicate(Module:Name/Arity). 552% ( atom(Name), integer(Arity) ) 553% -> ( functor(Head,Name,Arity), 554% current_predicate(_,Module:Head) 555% ) 556% ; ( current_predicate(_,Module:Head), 557% functor(Head,Name,Arity) 558% ) 559% . 560 561% (ground(functor(Head,Name,Arity), 562% predicate_property(Module:Head,visible). 563% 564% predicate_property(Head,visible) was created by Jan Wielemaker 565% during his visit to our group in Nov. 2011. It is intended as 566% a better behaved alternative to the inconsistent versions of 567% current_predicate/1 and /2. It is documented as: 568% True when predicate can be called without raising a predicate 569% existence error. This means that the predicate is (1) 570% defined, (2) can be inherited from one of the default modules 571% (see default_module/2) or (3) can be autoloaded. The behaviour 572% is logically consistent iff the propery visible is provided 573% explicitly. If the property is left unbound, only defined 574% predicates are enumerated. 575% However, the following does not seem really encouraging: 576% 37 ?- utils4modules:is_inconsistent( A,B ) . 577% A = 1547, <- failed current_predicate when visible suceeds 578% B = 933234. <- failed visible when current_predicate succeeds 579% 580% 38 ?- count( predicate_property(Module:Head,visible), N). 581% N = 1206199. 582% 583% 39 ?- count( current_predicate(Module:Name/Arity), N). 584% N = 17356. 585 586 587% <-- Beware of current_predicate/2: It hides system modules! 588% Only current_predicate/1 returns ALL modules that see Name/Arity, 589% including (hidden) system modules, such as '$syspreds'. 590% BUT it does it only if Name AND Arity are instantiated. 591% If only Name is instantiated, current_predicate/1 only returns 592% non-system modules that actually CALL Name/_. 593 594/* 595Inconsistent behaviour of current_predicate(M:F/N): 596 5973 ?- F=visible,current_predicate(M:F/N). 598F = visible, 599M = system, 600N = 1 ; 601 602F = visible, 603M = gui_tracer, 604N = 1 ; 605 606false. 607 6084 ?- F=visible,M='$syspreds', current_predicate(M:F/N). 609M = '$syspreds', 610F = visible, 611N = 1 ; 612 613false. 614 6155 ?- F=visible,N=1,findall(M:F/N, current_predicate(M:F/N), All), length(All,L). 616F = visible, 617N = 1, 618All = [emacs_buffer:visible/1, pce_hyper:visible/1, make:visible/1, 'condor.depend.expand.dnf':visible/1, targetModule:visible/1, prolog_break:visible/1, 619utils4modules:visible/1, emacs_fundamental_mode:... / ..., ... : ...|...], 620L = 203. 621*/ 622======= 623 624 625>>>>>>> 92defde0ffaad6ef7bd1d65d2c68e72011c7c32c