14
15:- module(pdt_prolog_metainference,
16 [ infer_meta/2, 17 infer_meta/3, 18 inferred_meta/2 19 ]). 20
21:- use_module(library(lists)). 22:- use_module(library(apply)). 23:- use_module(pdt_prolog_library(utils4modules_visibility)). 24:- use_module(pdt_prolog_library(lists)). 25:- use_module(pdt_meta_specification). 26
27reset :-
28 retractall(inferred_meta_pred(_, _, _)).
29
30run :-
31 run(1).
32
33run(Run) :-
34 statistics(cputime, CPU0),
35 format('Starting meta inference iteration ~w~n', [Run]),
36 findall(Module:MetaSpec, (
37 declared_in_module(Module, Name, Arity, Module),
38 functor(Head, Name, Arity),
39 \+ predicate_property(Module:Head, built_in),
40 \+ predicate_property(Module:Head, foreign),
41 \+ predicate_property(Module:Head, number_of_clauses(0)),
42 do_infer_meta(Module:Head, MetaSpec),
43 ( inferred_meta_pred(Head, Module, ExistingMetaSpec)
44 -> ( MetaSpec == ExistingMetaSpec
45 -> fail
46 ; retract(inferred_meta_pred(Head, Module, ExistingMetaSpec)),
47 assertz(inferred_meta_pred(Head, Module, MetaSpec))
48 )
49 ; assertz(inferred_meta_pred(Head, Module, MetaSpec))
50 )
51 ), NewOrModifiedMetaSpecs),
52 forall(member(Module:MetaSpec, NewOrModifiedMetaSpecs), format('% :- meta_predicate ~w:~w.~n', [Module, MetaSpec])),
53 statistics(cputime, CPU1),
54 CPU is CPU1 - CPU0,
55 length(NewOrModifiedMetaSpecs, NewOrModified),
56 format('Finished meta inference iteration ~w: ~w meta predicates found or modified in ~f sec.~n', [Run, NewOrModified, CPU]),
57 ( NewOrModified > 0
58 -> NextRun is Run + 1,
59 run(NextRun)
60 ; true
61 ).
62
63:- meta_predicate
64 inferred_meta(:, ?),
65 infer_meta(:, -),
66 infer_meta(:, -, -). 67
68:- dynamic
69 inferred_meta_pred/3.
92inferred_meta(M:Head, MetaSpec) :-
93 inferred_meta_pred(Head, M, MetaSpec).
94inferred_meta(M:Head, MetaSpec) :-
95 predicate_property(M:Head, imported_from(From)),
96 inferred_meta_pred(Head, From, MetaSpec).
105infer_meta(M:Head, MetaSpec) :-
106 infer_meta(M:Head, MetaSpec, _).
107
108infer_meta(M:Head, MetaSpec, NewOrUpdated) :-
109 predicate_property(M:Head, imported_from(From)), !,
110 do_infer_meta(From:Head, MetaSpec),
111 update_inferred_metaspec(Head, From, MetaSpec, NewOrUpdated).
112infer_meta(M:Head, MetaSpec, NewOrUpdated) :-
113 do_infer_meta(M:Head, MetaSpec),
114 update_inferred_metaspec(Head, M, MetaSpec, NewOrUpdated).
115
116update_inferred_metaspec(Head, M, NewMetaSpec, NewOrUpdated) :-
117 inferred_meta_pred(Head, M, OldMetaSpec),
118 !,
119 ( OldMetaSpec == NewMetaSpec
120 -> NewOrUpdated = false
121 ; retract(inferred_meta_pred(Head, M, OldMetaSpec)),
122 assertz(inferred_meta_pred(Head, M, NewMetaSpec)),
123 NewOrUpdated = true
124 ).
125update_inferred_metaspec(Head, M, NewMetaSpec, true) :-
126 assertz(inferred_meta_pred(Head, M, NewMetaSpec)).
127
128:- meta_predicate
129 do_infer_meta(:, -). 130
131do_infer_meta(Module:AHead, MetaSpec):-
132 functor(AHead, Functor, Arity),
133 functor(Head, Functor, Arity), 134 findall(MetaTerm,
135 meta_pred_args_in_clause(Module, Head, MetaTerm),
136 MetaTerms),
137 MetaTerms \== [],
138 combine_meta_args(MetaTerms, MetaTerm),
139 meta_terms_to_arg_specs_in_head(MetaTerm, MetaSpec).
144meta_pred_args_in_clause(Module, Head, MetaTermHead) :-
145 catch(clause(Module:Head, Body), _, fail),
146 annotate_meta_vars_in_body(Body, Module),
147 meta_term_head(Head, MetaTermHead).
162:- discontiguous(annotate_meta_vars_in_body/2). 163annotate_meta_vars_in_body(A, _) :-
164 atomic(A), !.
165annotate_meta_vars_in_body(Var, _) :-
166 var(Var), !,
167 annotate(0, Var).
168annotate_meta_vars_in_body(Module:Term, _) :- !,
169 ( atom(Module)
170 -> annotate_meta_vars_in_body(Term, Module)
171 ; var(Module)
172 -> annotate(m, Module)
173 ; true 174 ). 175annotate_meta_vars_in_body((TermA, TermB), Module) :- !,
176 annotate_meta_vars_in_body(TermB, Module),
177 annotate_meta_vars_in_body(TermA, Module).
178annotate_meta_vars_in_body((TermA; TermB), Module) :- !,
179 ( annotate_meta_vars_in_body(TermB, Module)
180 ; annotate_meta_vars_in_body(TermA, Module)
181 ).
182annotate_meta_vars_in_body((TermA->TermB), Module) :- !,
183 annotate_meta_vars_in_body(TermB, Module),
184 annotate_meta_vars_in_body(TermA, Module).
185annotate_meta_vars_in_body((TermA*->TermB), Module) :- !,
186 annotate_meta_vars_in_body(TermB, Module),
187 annotate_meta_vars_in_body(TermA, Module).
188annotate_meta_vars_in_body(A=B, _) :-
189 !,
190 unifiable(A, B, Unifiers),
191 new_aliases(Unifiers).
199new_aliases([]).
200new_aliases([A = B|Aliases]) :-
201 ( var(B)
202 -> merge_variable_annotations(A, B),
203 new_alias(A, B),
204 new_alias(B, A)
205 ; new_alias(A, B)
206 ),
207 new_aliases(Aliases).
213merge_variable_annotations(V1, V2) :-
214 ( get_attr(V1, pmi, Meta1)
215 -> ( get_attr(V2, pmi, Meta2)
216 -> 217 get_aliased(Meta1, Aliased1), 218 get_aliased(Meta2, Aliased2),
219 merge_annotations(Meta1, Meta2, MetaMerged), 220 duplicate_term(MetaMerged, MetaMergedCopy), 221 set_aliased(MetaMerged, Aliased1), 222 put_attr(V1, pmi, MetaMerged),
223 set_aliased(MetaMergedCopy, Aliased2),
224 put_attr(V2, pmi, MetaMergedCopy)
225 ; 226 duplicate_term(Meta1, MetaCopy), 227 set_aliased(MetaCopy, []), 228 put_attr(V2, pmi, MetaCopy)
229 )
230 ; ( get_attr(V2, pmi, Meta2)
231 -> 232 duplicate_term(Meta2, MetaCopy), 233 set_aliased(MetaCopy, []), 234 put_attr(V1, pmi, MetaCopy)
235 ; 236 true
237 )
238 ).
249new_alias(A, B) :-
250 ( get_attr(A, pmi, Meta)
251 -> get_aliased(Meta, Aliases),
252 ( eq_member(B, Aliases)
253 -> true
254 ; annotate(aliased(B), A),
255 check_for_unifiers(Aliases, B)
256 )
257 ; annotate(aliased(B), A)
258 ).
266check_for_unifiers([], _).
267check_for_unifiers([Alias|Aliases], Var) :-
268 unifiable(Alias, Var, Unifiers),
269 new_aliases(Unifiers),
270 check_for_unifiers(Aliases, Var).
271
272annotate_meta_vars_in_body(functor(Term, Functor, Arity), _Module) :-
273 !,
274 ( var(Term),
275 var_is_meta_called(Term, Annotation) 276 -> ( var(Functor)
277 -> ( integer(Arity)
278 -> annotate(has_arity(Arity, Annotation), Functor) 279 ; annotate(functor(Annotation), Functor) 280 )
281 ; true
282 ),
283 ( var(Arity)
284 -> annotate(arity(Annotation), Arity)
285 ; true
286 )
287 ; true
288 ).
296var_is_meta_called(Var, MetaAnnotations) :-
297 get_attr(Var, pmi, Meta),
298 setof(Annotation,
299 ( get_metacalled(Meta, Metacalled),
300 member(Annotation, Metacalled)
301 ; get_existential(Meta, ^),
302 Annotation = ^
303 ),
304 MetaAnnotations0),
305 remove_list_if_possible(MetaAnnotations0, MetaAnnotations),
306 !.
307
308annotate_meta_vars_in_body(atom_concat(A, B, C), _Module) :-
309 !,
310 ( var(C)
311 -> ( var_is_functor_or_meta_called(C, Annotation)
312 -> annotate_atom_concat(A, B, Annotation)
313 ; true
314 )
315 ; true
316 ).
325var_is_functor_or_meta_called(Var, MetaAnnotations) :-
326 get_attr(Var, pmi, Meta),
327 setof(Annotation,
328 ( get_metacalled(Meta, Metacalled),
329 member(Annotation, Metacalled)
330 ; get_existential(Meta, ^),
331 Annotation = ^
332 ; get_components(Meta, Components),
333 member(Annotation, Components),
334 ( Annotation = functor(_)
335 ; Annotation = has_arity(_, _)
336 )
337 ),
338 MetaAnnotations0),
339 remove_list_if_possible(MetaAnnotations0, MetaAnnotations),
340 !.
341
342annotate_atom_concat(A, B, Annotation) :-
343 var(A), var(B), !,
344 annotate(is_prefix(Annotation), A),
345 annotate(is_suffix(Annotation), B).
346annotate_atom_concat(A, B, Annotation) :-
347 atomic(A), var(B), !,
348 annotate(add_prefix(A, Annotation), B).
349annotate_atom_concat(A, B, Annotation) :-
350 var(A), atomic(B), !,
351 annotate(add_suffix(B, Annotation), A).
352annotate_atom_concat(_, _, _).
353
354annotate_meta_vars_in_body(Term =.. List, _Module) :-
355 !,
356 ( var(Term),
357 var_is_meta_called(Term, Annotation)
358 -> ( var(List)
359 -> annotate(univ_list(Annotation), List)
360 ; ( List = [Functor|Args],
361 var(Functor)
362 -> ( finite_length(Args, ArgsLength)
363 -> annotate(has_arity(ArgsLength, Annotation), Functor)
364 ; annotate(functor(Annotation), Functor)
365 )
366 ; true
367 )
368 )
369 ; true
370 ).
371
372annotate_meta_vars_in_body(asserta(Clause), _Module) :-
373 !,
374 annotate_database_argument(Clause).
375annotate_meta_vars_in_body(assert(Clause), _Module) :-
376 !,
377 annotate_database_argument(Clause).
378annotate_meta_vars_in_body(assertz(Clause), _Module) :-
379 !,
380 annotate_database_argument(Clause).
381annotate_meta_vars_in_body(retract(Clause), _Module) :-
382 !,
383 annotate_database_argument(Clause).
384annotate_meta_vars_in_body(retractall(Clause), _Module) :-
385 !,
386 annotate_database_argument(Clause).
387
388annotate_database_argument(Clause) :-
389 var(Clause),
390 !,
391 annotate(database, Clause).
392annotate_database_argument(Module:Clause) :-
393 !,
394 ( var(Module)
395 -> annotate(m, Module)
396 ; true
397 ),
398 ( var(Clause)
399 -> annotate(database, Clause)
400 ; true
401 ).
402annotate_database_argument(_Clause).
403
404annotate_meta_vars_in_body(Goal, Module) :-
405 extended_meta_predicate(Module:Goal, Head),
406 !,
407 functor(Goal, _, Arity),
408 annotate_meta_args(1, Arity, Goal, Head, Module).
409annotate_meta_vars_in_body(Goal, Module) :- 410 predicate_property(Module:Goal, meta_predicate(Head)),
411 !,
412 functor(Goal, _, Arity),
413 annotate_meta_args(1, Arity, Goal, Head, Module).
414annotate_meta_vars_in_body(Goal, Module) :-
415 inferred_meta(Module:Goal, Head),
416 !,
417 functor(Goal, _, Arity),
418 annotate_meta_args(1, Arity, Goal, Head, Module).
419annotate_meta_vars_in_body(_, _).
424annotate_meta_args(I, Arity, Goal, MetaSpec, Module) :-
425 I =< Arity, !,
426 arg(I, MetaSpec, MetaArg),
427 arg(I, Goal, Arg),
428 annotate_meta_arg(MetaArg, Arg, Module),
429 I2 is I + 1,
430 annotate_meta_args(I2, Arity, Goal, MetaSpec, Module).
431annotate_meta_args(_, _, _, _, _).
432
433annotate_meta_arg(Spec, Arg, _) :-
434 var(Arg), !,
435 annotate(Spec, Arg).
436annotate_meta_arg(0, Arg, Module) :- !,
437 annotate_meta_vars_in_body(Arg, Module).
438annotate_meta_arg(N, Arg, Module) :-
439 integer(N),
440 callable(Arg), !,
441 Arg =.. List,
442 length(Extra, N),
443 append(List, Extra, ListX),
444 ArgX =.. ListX,
445 annotate_meta_vars_in_body(ArgX, Module).
446annotate_meta_arg(Spec, Arg, _) :-
447 ( Spec == :
448 ; meta_calling_specifier(Spec)
449 ),
450 compound(Arg),
451 Arg = Module:_,
452 var(Module), !,
453 annotate(m, Module).
454annotate_meta_arg(_,_,_).
470annotate([], _) :- !.
471annotate([Annotation|Annotations], Var) :-
472 !,
473 annotate(Annotation, Var),
474 annotate(Annotations, Var).
475annotate(aliased(Alias), Var) :-
476 !,
477 get_or_create_meta(Var, Meta),
478 add_aliased(Meta, Alias),
479 put_attr(Var, pmi, Meta).
480annotate(^, Var) :-
481 !,
482 get_or_create_meta(Var, Meta),
483 add_existential(Meta, ^),
484 put_attr(Var, pmi, Meta).
485annotate(:, Var) :-
486 !,
487 get_or_create_meta(Var, Meta),
488 add_msensitive(Meta, :),
489 put_attr(Var, pmi, Meta).
490annotate(m, Var) :-
491 !,
492 get_or_create_meta(Var, Meta),
493 add_module(Meta, m),
494 put_attr(Var, pmi, Meta).
495annotate(*, Var) :-
496 !,
497 get_or_create_meta(Var, Meta),
498 add_bottom(Meta, *),
499 put_attr(Var, pmi, Meta).
500annotate(MetaCall, Var) :-
501 meta_calling_specifier(MetaCall),
502 !,
503 get_or_create_meta(Var, Meta),
504 add_metacalled(Meta, MetaCall),
505 put_attr(Var, pmi, Meta).
506annotate(Component, Var) :-
507 component_specifier(Component),
508 !,
509 get_or_create_meta(Var, Meta),
510 add_components(Meta, Component),
511 put_attr(Var, pmi, Meta).
512annotate(Mode, Var) :-
513 mode_specifier(Mode),
514 !,
515 get_or_create_meta(Var, Meta),
516 add_mode(Meta, Mode),
517 put_attr(Var, pmi, Meta).
518annotate(_, _).
519
521meta_calling_specifier(I) :- integer(I), !. 522meta_calling_specifier(^). 523meta_calling_specifier(//). 524meta_calling_specifier(database). 525
528component_specifier(functor(_M)). 529component_specifier(add_prefix(_P, _M)). 530component_specifier(add_suffix(_S, _M)). 531component_specifier(is_prefix(_M)). 532component_specifier(is_suffix(_M)). 533
534component_specifier(has_arity(_,_)). 535
536component_specifier(arity(_)). 537
538component_specifier(univ_list(_Meta)). 539 540
541mode_specifier(+).
542mode_specifier(-).
543mode_specifier(?).
544
545
546get_or_create_meta(Var, Meta) :-
547 ( get_attr(Var, pmi, Meta)
548 -> true
549 ; new_meta(Meta)
550 ).
551
552new_meta( meta([],[],[],[],[],[],[],[]) ).
553
554get_aliased(Meta,Value) :- arg(1,Meta,Value).
555get_metacalled(Meta,Value) :- arg(2,Meta,Value).
556get_components(Meta,Value) :- arg(3,Meta,Value).
557get_existential(Meta,Value):- arg(4,Meta,Value).
558get_msensitive(Meta,Value) :- arg(5,Meta,Value).
559get_module(Meta,Value) :- arg(6,Meta,Value).
560get_mode(Meta,Value) :- arg(7,Meta,Value).
561get_bottom(Meta,Value) :- arg(8,Meta,Value).
562
563set_aliased(Meta,Value) :- setarg(1,Meta,Value).
564set_metacalled(Meta,Value) :- setarg(2,Meta,Value).
565set_components(Meta,Value) :- setarg(3,Meta,Value).
566set_existential(Meta,Value):- setarg(4,Meta,Value).
567set_msensitive(Meta,Value) :- setarg(5,Meta,Value).
568set_module_(Meta,Value) :- setarg(6,Meta,Value).
569set_mode(Meta,Value) :- setarg(7,Meta,Value).
570set_bottom(Meta,Value) :- setarg(8,Meta,Value).
571
572add_aliased(Meta,Value) :- get_aliased(Meta, OldValue), merge_aliased([Value], OldValue, NewValue), set_aliased(Meta, NewValue).
573add_metacalled(Meta,Value) :- get_metacalled(Meta, OldValue), merge_metacalled([Value], OldValue, NewValue), set_metacalled(Meta, NewValue).
574add_components(Meta,Value) :- get_components(Meta, OldValue), merge_components([Value], OldValue, NewValue), set_components(Meta, NewValue).
575add_existential(Meta,Value):- set_existential(Meta, Value).
576add_msensitive(Meta,Value) :- set_msensitive(Meta, Value).
577add_module(Meta,Value) :- set_module_(Meta, Value).
578add_mode(Meta,Value) :- get_mode(Meta, OldValue), merge_mode(OldValue, Value, NewValue), set_mode(Meta, NewValue).
579add_bottom(Meta,Value) :- set_bottom(Meta, Value).
580
581merge_aliased(Value1, Value2, Value3) :- eq_union(Value1, Value2, Value3).
582
583merge_metacalled(Value1, Value2, Value3) :- eq_union(Value1, Value2, Value3).
584
585merge_components(Value1, Value2, Value3) :- eq_union(Value1, Value2, Value3).
586
587merge_existential(Value, Value, Value) :- !.
588merge_existential(_, _, ^ ).
589
590merge_msensitive(Value, Value, Value) :- !.
591merge_msensitive(_, _, : ).
592
593merge_module(Value, Value, Value) :- !.
594merge_module(_, _, m ).
595
596merge_mode(Value, Value, Value) :- !.
597merge_mode([], Value, Value) :- !.
598merge_mode(Value, [], Value) :- !.
599merge_mode(_, _, ? ).
600
601merge_bottom(Value, Value, Value) :- !.
602merge_bottom(_, _, * ).
609eq_union([], L, L) :- !.
610eq_union([H|T], L, R) :-
611 eq_member(H, L),
612 !,
613 eq_union(T, L, R).
614eq_union([H|T], L, [H|R]) :-
615 eq_union(T, L, R).
620eq_member(E, L) :-
621 member(E2, L),
622 E == E2.
629merge_annotations(Meta1, Meta2, Meta) :-
630 new_meta(Meta),
631 get_metacalled( Meta1, Metacalled1) , get_metacalled( Meta2, Metacalled2) , merge_metacalled( Metacalled1, Metacalled2, Metacalled) , set_metacalled( Meta, Metacalled),
632 get_components( Meta1, Components1) , get_components( Meta2, Components2) , merge_components( Components1, Components2, Components) , set_components( Meta, Components),
633 get_existential(Meta1, Existential1), get_existential(Meta2, Existential2), merge_existential(Existential1, Existential2, Existential), set_existential(Meta, Existential),
634 get_msensitive( Meta1, MSensitive1) , get_msensitive( Meta2, MSensitive2) , merge_msensitive( MSensitive1, MSensitive2, MSensitive) , set_msensitive( Meta, MSensitive),
635 get_module( Meta1, Module1) , get_module( Meta2, Module2) , merge_module( Module1, Module2, Module) , set_module_( Meta, Module),
636 get_mode( Meta1, Mode1) , get_mode( Meta2, Mode2) , merge_mode( Mode1, Mode2, Mode) , set_mode( Meta, Mode),
637 get_bottom( Meta1, Bottom1) , get_bottom( Meta2, Bottom2) , merge_bottom( Bottom1, Bottom2, Bottom) , set_bottom( Meta, Bottom).
646meta_term_head(Head, MetaTermHead) :-
647 functor(Head, Name, Arity),
648 functor(MetaTermHead, Name, Arity),
649 meta_args(1, Arity, Head, MetaTermHead, HasMeta),
650 HasMeta == true. 651
652meta_args(I, Arity, Head, Meta, HasMeta) :-
653 I =< Arity, !,
654 arg(I, Head, HeadArg),
655 arg(I, Meta, MetaArg),
656 meta_term_of_var(HeadArg, MetaArg, HasMeta),
657 I2 is I + 1,
658 meta_args(I2, Arity, Head, Meta, HasMeta).
659meta_args(_, _, _, _, _).
670meta_term_of_var(HeadArg, MetaTerm, IsMetaArg) :-
671 get_attr(HeadArg, pmi, MetaTerm),
672 !,
673 set_aliased(MetaTerm, []),
674 ( has_meta_calling_or_component_or_msensitive_annotation(MetaTerm)
675 -> IsMetaArg = true
676 ; true
677 ).
678meta_term_of_var(HeadArg, MetaTerm, IsMetaArg) :-
679 compound(HeadArg),
680 HeadArg = M:_,
681 get_attr(M, pmi, MMeta),
682 get_module(MMeta, m),
683 !,
684 new_meta(MetaTerm),
685 set_msensitive(MetaTerm, :),
686 IsMetaArg = true.
687meta_term_of_var(_, NewMeta, _) :-
688 new_meta(NewMeta).
689
690has_meta_calling_or_component_or_msensitive_annotation(Meta) :-
691 ( get_metacalled(Meta, Metacalled),
692 member(_, Metacalled)
693 ; get_existential(Meta, ^)
694 ; get_components(Meta, Components),
695 member(_, Components)
696 ; get_msensitive(Meta, :)
697 ),
698 !.
699
700remove_list_if_possible([], _) :- !, fail.
701remove_list_if_possible([X], X) :- !.
702remove_list_if_possible(List, List).
708combine_meta_args([], []) :- !.
709combine_meta_args([List], List) :- !.
710combine_meta_args([Spec,Spec|Specs], CombinedArgs) :- !,
711 combine_meta_args([Spec|Specs], CombinedArgs).
712combine_meta_args([Spec1,Spec2|Specs], CombinedArgs) :-
713 Spec1 =.. [Name|Args1],
714 Spec2 =.. [Name|Args2],
715 maplist(merge_annotations, Args1, Args2, Args),
716 Spec =.. [Name|Args],
717 combine_meta_args([Spec|Specs], CombinedArgs).
723meta_terms_to_arg_specs_in_head(HeadWithMetaTerms, MetaSpec) :-
724 HeadWithMetaTerms =.. [Name|MetaTerms],
725 maplist(meta_term_to_arg_spec, MetaTerms, ArgSpecs),
726 MetaSpec =.. [Name|ArgSpecs].
744meta_term_to_arg_spec(MetaTerm, ArgSpec) :-
745 get_metacalled_or_existential_or_msensitive(MetaTerm, MetacalledOrExistential),
746 get_components(MetaTerm, Components),
747 append(MetacalledOrExistential, Components, ArgSpec0),
748 sort(ArgSpec0, ArgSpec1),
749 remove_list_if_possible(ArgSpec1, ArgSpec),
750 !.
751
752meta_term_to_arg_spec(MetaTerm, ArgSpec) :-
753 get_mode(MetaTerm, ArgSpec),
754 ArgSpec \== [],
755 !.
756
757meta_term_to_arg_spec(_, *).
758
759get_metacalled_or_existential_or_msensitive(MetaTerm, Metacalled) :-
760 get_metacalled(MetaTerm, Metacalled),
761 Metacalled \== [],
762 !.
763get_metacalled_or_existential_or_msensitive(MetaTerm, [^]) :-
764 get_existential(MetaTerm, ^),
765 !.
766get_metacalled_or_existential_or_msensitive(MetaTerm, [:]) :-
767 get_msensitive(MetaTerm, :),
768 !.
769get_metacalled_or_existential_or_msensitive(_MetaTerm, []).
770
771
772attr_unify_hook(A0, Other) :-
773 writeln(attr_unify_hook(A0, Other))
Infer meta-predicate properties
This module infers meta-predicate properties by inspecting the clauses of predicates that call other predicates. This is extremely useful for program analysis and refactoring because many programs `in the wild' have incomplete or incorrect meta-predicate information.