1:- module(pure,
    2          [ is_pure_pred/1,
    3            is_pure_pred/2,
    4            is_pure_clause/1,
    5            is_pure_body/1,
    6            is_pure_body/2,
    7            is_impure/1
    8          ]).    9
   10:- use_module(library(lists)).   11:- use_module(library(resolve_calln)).   12:- use_module(library(qualify_meta_goal)).   13
   14:- meta_predicate
   15        is_impure(0 ),
   16        is_pure_pred(0 ),
   17        is_pure_pred(0, 1 ),
   18        is_pure_pred(0, 1, +),
   19        is_pure_body(0 ),
   20        is_pure_body(0, 1 ).   21
   22is_impure(_:(\+ _)) :- !, fail.
   23is_impure(M:Head) :- \+ predicate_property(M:Head, interpreted).
   24
   25is_pure_pred(Head) :-
   26    is_pure_pred(Head, is_impure, []).
 is_pure_pred(:Pred, :IsImpure) is semidet
Succeeds if the predicate is free of literals that makes IsImpure succeed, that is, calls to IsImpure fails for at least one of the dependent predicates. If IsImpure is is_impure/1, it tests that the predicate is a pure-prolog one, that is, it does not have side-effects and only consists of calls to interpreted predicates and trivial built-ins like true or false. Fails otherwise or if it is unable to determine it.
   37is_pure_pred(Head, IsImpure) :-
   38    is_pure_pred(Head, IsImpure, []).
 is_pure_clause(Ref) is semidet
Succeeds if the clause referenced by Ref has been implemented using only pure-prolog predicates.
   45is_pure_clause(Ref) :-
   46    is_pure_clause(Ref, is_impure, []).
   47
   48is_pure_pred(M:Head, IsImpure, Stack1) :-
   49    \+ call(IsImpure, M:Head),
   50    findall(Ref, ( catch(clause(M:Head, _, Ref), _, fail),
   51                   \+ memberchk(Ref, Stack1)
   52                 ), RefL),
   53    append(RefL, Stack1, Stack),
   54    forall(member(Ref, RefL),
   55           is_pure_clause(Ref, IsImpure, Stack)).
   56
   57is_pure_clause(Ref, IsImpure, Stack) :-
   58    clause_property(Ref, module(CM)),
   59    catch(clause(M:Head, Body, Ref), _, fail),
   60    % is not defined in init.pl:
   61    M:Head \== CM:Body,
   62    M:call(Head) \== CM:Body,
   63    is_pure_body(Body, CM, IsImpure, Stack).
   64
   65% Note: ->/2, \+/1, *->/2, !, are not consider pure prolog, you can prove that by
   66% implementing var/1 using those, since var/1 is not pure prolog. For instance:
   67%
   68% var(A) :- \+ (A = a), \+ (A = b).
   69
   70% In general, any predicate that check the instantiation status of a variable is
   71% not pure-prolog
   72
   73is_pure_body(M:G) :-
   74    is_pure_body(G, M, is_impure, []).
   75
   76is_pure_body(M:G, IsImpure) :-
   77    is_pure_body(G, M, IsImpure, []).
   78
   79is_pure_body(G, M, IsImpure, _) :-
   80    var(G),
   81    !,
   82    freeze(G, is_pure_pred(M:G, IsImpure)).
   83is_pure_body(true, _, _, _) :- !.
   84is_pure_body(fail, _, _, _) :- !.
   85is_pure_body(_=_,  _, _, _) :- !.
   86is_pure_body(\+ _, _, _, _) :- !, fail.
   87is_pure_body(@(G, CM), _, IsImpure, Stack) :-
   88    !,
   89    strip_module(CM:G, M, H),
   90    is_pure_body_mod(H, M, CM, IsImpure, Stack).
   91is_pure_body(M:G, _, IsImpure, Stack) :-
   92    !,
   93    is_pure_body_mod(G, M, M, IsImpure, Stack).
   94is_pure_body((A,B), M, IsImpure, Stack) :-
   95    !,
   96    is_pure_body(A, M, IsImpure, Stack),
   97    is_pure_body(B, M, IsImpure, Stack).
   98is_pure_body((A;B), M, IsImpure, Stack) :-
   99    !,
  100    is_pure_body(A, M, IsImpure, Stack),
  101    is_pure_body(B, M, IsImpure, Stack).
  102is_pure_body(CallN, M, IsImpure, Stack) :-
  103    do_resolve_calln(CallN, Call),
  104    is_pure_body(Call, M, IsImpure, Stack).
  105is_pure_body(phrase(DCG, L, T), M, IsImpure, Stack) :-
  106    !,
  107    dcg_translate_rule(('$head$' --> DCG, '$sink$'), _, ('$head$'(L, _) :- Lits, '$sink$'(T, _)), _),
  108    is_pure_body(Lits, M, IsImpure, Stack).
  109is_pure_body(phrase(DCG, L), M, IsImpure, Stack) :-
  110    !,
  111    is_pure_body(phrase(DCG, L, []), M, IsImpure, Stack).
  112is_pure_body(H, M, IsImpure, Stack) :-
  113    ( predicate_property(M:H, meta_predicate(Meta))
  114    ->qualify_meta_goal(M:H, Meta, Goal)
  115    ; Goal = H
  116    ),
  117    is_pure_pred(M:Goal, IsImpure, Stack).
  118
  119/*
  120is_pure_body_mod(G, M, CM, Stack) :-
  121    ( atom(M),
  122      atom(CM)
  123    ->setup_call_cleanup(
  124          ( '$current_source_module'(OldM),
  125            '$set_source_module'(CM)
  126          ),
  127          is_pure_body(G, M, Stack),
  128          '$set_source_module'(OldM))
  129    ; true
  130    ).
  131*/
  132
  133is_pure_body_mod(H, M, _, IsImpure, Stack) :-
  134    is_pure_body(H, M, IsImpure, Stack)