1/*****************************************************************************
    2 * This file is part of the Prolog Development Tool (PDT)
    3 * 
    4 * WWW: http://sewiki.iai.uni-bonn.de/research/pdt/start
    5 * Mail: pdt@lists.iai.uni-bonn.de
    6 * Copyright (C): 2004-2012, CS Dept. III, University of Bonn
    7 * 
    8 * All rights reserved. This program is  made available under the terms
    9 * of the Eclipse Public License v1.0 which accompanies this distribution,
   10 * and is available at http://www.eclipse.org/legal/epl-v10.html
   11 * 
   12 ****************************************************************************/
   13
   14:- module(metafile_referencer, [file_references_for_metacall/3,	%Arg1=ContextModule %Arg2=MetaCall %Arg3=References (see description)
   15								file_references_for_call/3,		%Arg1=ContextModule %Arg2=Term %Arg3=FileSet
   16								is_metaterm/3					%Arg1=ContextModule %Arg2=Literal %Arg3=MetaArgument
   17								]).   18								
   19:- use_module(pdt_prolog_library(utils4modules)).   20
   21:- use_module(library(lists)).   22
   23:- dynamic user_defined_meta_pred/4.	%user_defined_meta_pred(Functor, Arity ,Module, MetaSpec)
   24
   25% F�R EVA: Dies Pr�dikat m�ssen wir noch mal besprechen. -- G.
   26
   27file_references_for_metacall(Module,MetaTerm,References):-
   28    is_metaterm(Module,MetaTerm,MetaArgs),			
   29    length(MetaArgs,Length),
   30    length(References,Length),
   31    nth1(N,MetaArgs,MArg),
   32    MArg=(ArgNr,Term),
   33	file_references_for_term(Module, Term, FileSet),
   34    nth1(N,References,(ArgNr,Term,FileSet)).
   35    
   36    
   37/* *
   38 * is_metaterm(?Module, -Literal, ?MetaArguments ) is non_det
   39 * is_metaterm(?Module, +Literal, ?MetaArguments ) is det
   40 *  Arg1 is a literal representing a metacall and 
   41 *  Arg2 is the list of its meta-arguments each of the form:
   42 *      (Original_argument_position, Argument).
   43 */
   44is_metaterm(Module, Literal, MetaArguments) :-
   45   \+(var(Literal)), !,
   46   functor(Literal,Functor,Arity),	
   47   (	Module = user
   48   ->	visible_in_module(CurrentModule, Functor, Arity)
   49   ;	(	visible_in_module(Module,Functor,Arity),
   50   			CurrentModule = Module
   51   		)
   52   	),	
   53   %predicate_property(Module:Literal,meta_predicate(MetaTerm)),
   54   is_meta_pred(CurrentModule, Literal, MetaTerm),	
   55   Literal =.. [Functor|Args],
   56   MetaTerm =.. [Functor|MetaArgs],
   57   collect_meta_args(Args,MetaArgs, MetaArguments ).
   58is_metaterm(Module, Literal, MetaArguments) :-
   59   visible_in_module(Module,Functor,Arity),
   60   functor(Literal,Functor,Arity),	
   61   %predicate_property(Module:Literal,meta_predicate(MetaTerm)),
   62   is_meta_pred(Module, Literal, MetaTerm),
   63   Literal =.. [Functor|Args],
   64   MetaTerm =.. [Functor|MetaArgs],
   65   collect_meta_args(Args,MetaArgs, MetaArguments ).
   66   
   67
   68%is_meta_pred(_, assert(_), assert(0)):- !.
   69%is_meta_pred(_, asserta(_), asserta(0)):- !.
   70%is_meta_pred(_, assertz(_), assertz(0)):- !.    
   71is_meta_pred(Module, Literal, MetaTerm):-	%TODO: auf built_in einschr�nken!
   72    predicate_property(Module:Literal,meta_predicate(MetaTerm)).
   73is_meta_pred(Module, Literal, MetaTerm):-    
   74    functor(Literal, Functor, Arity),
   75    user_defined_meta_pred(Functor, Arity, Module, MetaTerm).
   76    
   77/* *
   78* collect_meta_args(+Args,+MetaArgs,?MetaArguments) is det
   79* 
   80* MetaArguments is unified to a list of all elements of Args that are defined
   81* as meta-arguments via the corresponding elements of MetaArgs.
   82* (extract_meta_args/3 is used to select the corresponding elements and to 
   83* build the entries of MetaArguments.)
   84* Fails if no MetaArguments can be found.
   85*/
   86collect_meta_args(Args,MetaArgs, MetaArguments ) :- 
   87	bagof( 
   88        Meta,
   89        extract_meta_argument(Args,MetaArgs, Meta),
   90        MetaArguments
   91    ).
   92    
   93extract_meta_argument(Args,MetaArgs, (N,NewArg) ) :- 
   94    nth1(N,MetaArgs,MArg),
   95    nth1(N,Args,Arg),
   96    additonal_parameters(MArg,Arg,NewArg).
   97
   98% If the meta-argument is not a variable,
   99% add as many parameters to it as indicated
  100% by the meta-argument specifier (0-9).
  101% Fail for (skip) parameters marked as ':'
  102% (= module-aware) but not as meta:
  103%additonal_parameters(':',Arg,Arg):- !.
  104additonal_parameters(0,Arg,Arg):- !.
  105additonal_parameters(N,Arg,Arg):-
  106    integer(N),
  107    var(Arg),!.
  108additonal_parameters(N,Arg,NewArg) :-
  109    integer(N),
  110	Arg =.. [Functor | Params],				
  111   	length(N_Elems,N),
  112   	append(Params,N_Elems,NewParams),
  113   	NewArg =.. [Functor | NewParams].
  114    
  115    
  116file_references_for_call(Module, Term, [(Module, 'any')]):-
  117    var(Term), !.
  118file_references_for_call(Module, Term, FileSet):-
  119    functor(Term,Name,Arity),
  120    findall( ContextFile,							
  121    		 (	defined_in_module(Module,Name,Arity),
  122    		    defined_in_file(Module,Name,Arity,_Nth,File,_Line),
  123    		 	ContextFile = (Module,File)
  124    		 ),
  125    		 Files
  126    ),
  127    not(Files = []), !,
  128    list_to_set(Files,FileSet).
  129file_references_for_call(Module, Term, FileSet):-
  130    functor(Term,Name,Arity),
  131    findall(	ContextFile,
  132    			(	(Module,Name,Arity,DeclModule),
  133    				module_property(DeclModule,file(File)),
  134    				predicate_property(DeclModule:Term,dynamic),
  135    				ContextFile = (Module,File)
  136    			),
  137    			Files
  138    ), 
  139    not(Files = []),  !,
  140    list_to_set(Files,FileSet).
  141file_references_for_call(Module, Term, [(Module, 'undefined')]):-
  142    functor(Term,Name,Arity),
  143	visible_in_module(Module,Name,Arity).   
  144
  145	
  146	
  147	
  148:- dynamic(new_found_meta_predicate/1).	
  149	
  150find_unknown_meta_predicates:-
  151    retractall(new_found_meta_predicate(_)),
  152	current_predicate(RefModule:F/A),     % For all defined predicates	
  153	functor(RefHead,F,A),   
  154	\+ predicate_property(RefModule:RefHead, built_in),
  155	\+ predicate_property(RefModule:RefHead, autoload(_)),
  156    nth_clause(RefModule:RefHead,_,Ref),   % For all their clauses
  157   	'$xr_member'(Ref, Module:Meta_Head),                  % Get a term referenced by that clause
  158   	
  159   	functor(Meta_Head,Name,Arity),
  160	known_meta_predicate(Module,Name,Arity,_Definition),
  161    
  162
  163	%hier m�sste ein XReferencer jetzt rein,
  164	%wenn man es richtig macht, sollten die variablen-Bindungen auch zu finden sein
  165	% vielleicht mal mit den call_edges versuchen - oberste ebene sollte ich ja finden, geschachteltes im n�chsten Schritt   	
  166   	assert(new_found_meta_predicate(RefModule:F/A)),
  167   	fail.
  168find_unknown_meta_predicates.
  169
  170
  171
  172
  173    
  174    
  175
  176
  177/*
  178 *	know_meta_predicat(?Module,?Name, ?Arity, ?MetaArgs) is nondet
  179 *
  180 *  succeds when the predicate represented by Arg1:Arg2/Arg3 
  181 *  is a meta-predicate. 
  182 *  In this case, Arg4 is the meta-predicate definition.
  183 **/
  184known_meta_predicate(Module,Name,Arity,Definition):-
  185    predicate_property(Module:Head,meta_predicate(Definition)),
  186    functor(Head,Name,Arity),
  187    visible_in_module(Module,Name,Arity)