Anderson Green
Anderson Green

Reputation: 31850

Expanding Prolog clauses with forall/2

I'm using clause/2 to transform some Prolog clauses in a compiler. I need to replace the head of each clause with its body, but clause/2 sometimes doesn't expand the clause in the way that it was originally written.

Here, clause/2 expands demo(A,B) to \+ (call(A),\+call(B)), instead of expanding its original definition:

:- use_module(prolog_to_minizinc).
:- initialization(main).

main :- 
        writeln(forall(A,B)),
        clause(demo(A,B),Clause),
        writeln(Clause).

demo(A,B) :-
    forall(A,B).

Is there another way to expand clauses, without modifying clauses that include forall/2?

Upvotes: 1

Views: 121

Answers (1)

Paulo Moura
Paulo Moura

Reputation: 18683

The unwanted expansion of the forall/2 goal is due to SWI-Prolog loading library(apply_macros) at startup. This library provides the expansion code for forall/2 and other predicates. Finding how library(apply_macros) is loaded is not trivial as setting the verbose_autoload flag to true in the ~/.config/swi-prolog/init.pl file doesn't print all libraries that are being auto-loaded at startup. On my laptop, using the current devel git version of SWI-Prolog (8.1.21-82-ge6e1d5376-DIRTY):

?- current_module(apply_macros).
true.

?- module_property(apply_macros, P).
P = class(library) ;
P = file('/Users/pmoura/lib/swipl/library/apply_macros.pl') ;
P = line_count(36) ;
P = exports([expand_phrase/2, expand_phrase/4]) .

?- source_file_property('/Users/pmoura/lib/swipl/library/apply_macros.pl', P).
P = modified(1547476368.0) ;
P = source(file) ;
P = module(apply_macros) ;
P = load_context(nb_set, '/Users/pmoura/lib/swipl/library/nb_set.pl':45, [imports([])]) ;
P = load_count(1) ;
P = number_of_clauses(52).

?- source_file_property('/Users/pmoura/lib/swipl/library/nb_set.pl', P).
P = modified(1547476368.0) ;
P = source(file) ;
P = module(nb_set) ;
P = load_context(solution_sequences, '/Users/pmoura/lib/swipl/library/solution_sequences.pl':46, []) ;
P = load_count(1) ;
P = number_of_clauses(13).

?- source_file_property('/Users/pmoura/lib/swipl/library/solution_sequences.pl', P).
P = modified(1574086719.0) ;
P = source(file) ;
P = module(solution_sequences) ;
P = load_context(editline, '/Users/pmoura/lib/swipl/library/editline.pl':59, []) ;
P = load_count(1) ;
P = number_of_clauses(49).

The file editline.pl provides the default convenient command-line history and other services. But if you switch to readline by adding to your ~/.config/swi-prolog/init.pl file the directive:

:- set_prolog_flag(readline, readline).

Then you get:

?- [user].
|: a(A,B) :- forall(A,B).
|: % user://1 compiled 0.00 sec, 1 clauses
true.

?- listing(a/2).
% autoloading user:listing/1 from /Users/pmoura/lib/swipl/library/listing
a(A, B) :-
    forall(A, B).

true.

This is a poor workaround but it may help you.

Upvotes: 2

Related Questions