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(metapred_finder, [	get_all_userdefined_meta_predicates/1,
   15							find_all_meta_predicates/0]).   16
   17:- use_module(library(lists)).   18:- use_module(metafile_referencer).   19:- use_module(pdt_prolog_library(utils4modules)).   20:- use_module(term_based_metapred_finder).   21:- use_module('../modules_and_visibility.pl').   22
   23
   24:- dynamic new_meta_pred/2.	%new_meta_pred(MetaSpec, Module)
   25
   26get_all_userdefined_meta_predicates(MetaPreds):-
   27    findall(
   28    	Module:NewMetaSpec,
   29    	metafile_referencer:user_defined_meta_pred(_Functor, _Arity, Module, NewMetaSpec),
   30    	MetaPreds
   31    ).
   32    
   33
   34find_all_meta_predicates:-
   35    initialize_meta_pred_search,
   36    repeat,
   37    	collect_candidates(Candidates),
   38    	forall(
   39    		(	member(Module:Candidate, Candidates),
   40    			(	Module = user
   41    			->	(	functor(Candidate, Functor, Arity),
   42    					visible_in_module(AModule,Functor,Arity),
   43    					infer_meta_arguments_for(AModule, Candidate, MetaSpec)
   44    				)	
   45    			;	infer_meta_arguments_for(Module,Candidate,MetaSpec)
   46    			)
   47 			),
   48 			assert(new_meta_pred(MetaSpec, Module))
   49		),
   50		(	new_meta_pred(_,_)
   51		->	(	prepare_next_step,
   52				fail
   53			)
   54		;	true
   55		),
   56	!.
   57	    
   58    
   59    
   60initialize_meta_pred_search:-
   61    retractall(metafile_referencer:user_defined_meta_pred(_,_,_,_)),
   62    retractall(new_meta_pred(_,_)),
   63    forall(	
   64    	(   find_predefined_metas(Spec, Module)
   65    	),
   66    	assert(new_meta_pred(Spec, Module))
   67    		%format('Initial: ~w:~w~n', [Module, Spec])
   68    ).
   69    
   70  
   71find_predefined_metas(Spec, Module):-
   72    defined_in(Module,Functor, Arity, Module),
   73    functor(Head,Functor,Arity),
   74    predicate_property(Module:Head, built_in),
   75   	predicate_property(Module:Head, meta_predicate(Spec)),
   76   	is_metaterm(Module, Head, MetaArgs),
   77    (MetaArgs \= []).
   78        
   79        
   80        
   81collect_candidates(Candidates):-
   82	findall(
   83		CandModule:Candidate,
   84    	(	new_meta_pred(MetaSpec, Module),
   85    		retract(new_meta_pred(MetaSpec, Module)),
   86    		functor(MetaSpec, Functor, Arity),
   87    		%visible_in_module(AModule, Functor, Arity),		%TODO: hier m�sste man eigentlich die Module suchen, die das Modul sehen
   88    														%		f�r die ..T-Fakten m�glich, aber nicht f�r die vordefinierten...
   89    														%		andererseits: der genaue Test ist ja eh sp�ter, hier nur Kandidaten.
   90    		(	parse_util:predicateT_ri(Functor,Arity,Module,PredId)
   91    		->	parse_util:call_edge(PredId,LiteralId)
   92			;	parse_util:call_built_in(Functor, Arity, Module, LiteralId)
   93			),
   94			parse_util:literalT(LiteralId,_ParentId,ClauseId,_AModule,_Functor,_Arity),
   95			parse_util:clauseT(ClauseId,_,CandModule,CandFunctor,CandArity),
   96			functor(Candidate, CandFunctor, CandArity),
   97			\+ (predicate_property(CandModule:Candidate, built-in))%,
   98			%format('Candidate: ~w:~w~n', [CandModule, Candidate])
   99        ),
  100        CandidateList
  101	), 
  102	list_to_set(CandidateList, Candidates).	
  103	
  104	
  105    
  106prepare_next_step:-
  107    forall(	
  108    	new_meta_pred(MetaSpec, Module),
  109    	(	functor(MetaSpec, Functor, Arity),
  110    		(	metafile_referencer:user_defined_meta_pred(Functor, Arity, Module, OldMetaSpec)
  111    		->	(	(MetaSpec \= OldMetaSpec)
  112    			->	(	combine_two_arg_lists(OldMetaSpec, MetaSpec, NewMetaSpec),
  113    					retractall(metafile_referencer:user_defined_meta_pred(Functor,Arity,Module,_)),
  114    					assert(metafile_referencer:user_defined_meta_pred(Functor, Arity, Module, NewMetaSpec))
  115    				)
  116    			;	retract(new_meta_pred(MetaSpec, Module))	% was already there, no need to handle it again 		
  117    			)
  118    		;	assert(metafile_referencer:user_defined_meta_pred(Functor, Arity, Module, MetaSpec)),
  119    			update_factbase(Functor, Arity, Module)
  120    		)
  121    	)
  122    ).
  123    
  124update_factbase(Functor, Arity, Module):-
  125    parse_util:predicateT_ri(Functor,Arity,Module,PId),
  126 	assert(parse_util:meta_predT(PId, found))