34
35:- module(unfold_calls,
36 [unfold_calls/4]). 37
38:- use_module(library(qualify_meta_goal)). 39
40:- multifile
41 unfold_call_hook/4. 42
43:- meta_predicate unfold_calls(+, +, 2, -). 44unfold_calls(Goal, CM, IsUnfold, Calls) :-
45 predicate_property(CM:Goal, implementation_module(M)),
46 findall(Call, ( unfold_call(Goal, CM, IsUnfold, [], Call),
47 \+ M:Goal =@= Call
48 ), Calls).
49
50unfold_call(Goal, _, _, _, _) :- var(Goal), !, fail.
51unfold_call(true, _, _, _, _) :- !, fail.
52unfold_call(call(Goal), CM, IsUnfold, NonUnfoldL, Call) :- !,
53 unfold_call(Goal, CM, IsUnfold, NonUnfoldL, Call).
54unfold_call(\+ Goal, CM, IsUnfold, NonUnfoldL, Call) :- !,
55 unfold_call(Goal, CM, IsUnfold, NonUnfoldL, Call).
56unfold_call(CM:Goal, _, IsUnfold, NonUnfoldL, Call) :-
57 nonvar(Goal), !,
58 unfold_call(Goal, CM, IsUnfold, NonUnfoldL, Call).
59unfold_call(Goal1, CM, IsUnfold, NonUnfoldL, Call) :-
60 CMGoal1 = CM:Goal1,
61 predicate_property(CMGoal1, implementation_module(M)),
62 qualify_meta_goal(CMGoal1, MGoal),
63 strip_module(MGoal, _, Goal),
64 ( unfold_call_hook(Goal, M, CM, Goal2)
65 *->
66 unfold_call(Goal2, CM, IsUnfold, NonUnfoldL, Call)
67 ; \+ \+ memberchk(M:Goal, NonUnfoldL)
68 ->Call = CM:Goal
69 ; \+ call(IsUnfold, Goal, M),
70 \+ ( predicate_property(CM:Goal, meta_predicate(S)),
71 arg(_, S, 0 )
72 )
73 ->Call = CM:Goal
74 ; ( nth_clause(CM:Goal, _Idx, Ref),
75 clause(M:Head, Body, Ref),
76 Body \== call(Head)
77 *->
78 clause_property(Ref, module(BM)),
79 ( subsumes_term(Head, Goal)
80 ->Goal = Head,
81 unfold_call(Body, BM, IsUnfold, NonUnfoldL, Call)
82 ; \+ Head \= Goal
83 ->copy_term(Goal, Head),
84 unfold_call(Body, BM, IsUnfold, [M:Head|NonUnfoldL], Call)
85 86 )
87 ; predicate_property(CM:Goal, meta_predicate(Spec)),
88 ( arg(N, Spec, S),
89 arg(N, Goal, A),
90 S = 0,
91 unfold_call(A, CM, IsUnfold, NonUnfoldL, Call)
92 )
93 )
94 )