Term expansion when loading compiled qlf files


I’m facing an issue with dynamically declaring predicates multifile using the term_expansion/2 hook when loading qlf files. The approach works fine if I run consult/1 on the non-compiled .pl code. Here is the term_expansion/2 declaration I’m using:

%Defined in a file named hook.pl
term_expansion(Head, [:- multifile(Declaration), Head]) :-
    Head \= begin_of_file,
    Head \= end_of_file,
    Head \= :-(_),
    prolog_load_context(source, Source),
    functor(Head, Name, Arity),
    (   seen_predicate(Source, Name, Arity) ->
      :  false
    ;   assertz(seen_predicate(Source, Name, Arity)), 
        Declaration = [Name/Arity]

To reproduce the warnings I get, assume we have two files fileA.pl and fileB.pl with the following contents:


likes(boy, apple).
eats(boy, apple).
likes(boy, orange).

Now, in the SWI-Prolog top-level, after loading hook.pl (which contains the term_expansion/2 declaration), if I run consult("./fileA.pl") followed by consult(“./fileB.pl”), everything works as expected.

However, if I compile the files whith qcompile/1 and load them with consult("./fileA.qlf") followed by consult("./fileB.qlf"), I get the following warning:

Warning: Redefined static procedure likes/2
Warning: Previously defined at /path/to/fileA.pl:1

For small files I can just ignore the warnings. However, when loading large files that contain predicates declared across files, the SWI-Prolog toplevel shows the above warnings and takes too long to load the qlf files. For instance, for a file that takes two minutes to load the pl version, it takes more than an hour and half to load the qlf version if the warning has been thrown.

How do I fix this? That is make term_expansion/2 work with qcompiled files.

1 Like

It should work fine, provided you make sure hook.pl is loaded when running qcompile/1. qcompile/1 translates the file to a qlf file that basically contains the VM instructions (byte codes). If you do any program transformations, the code to do these transformations should be loaded when compiling.

1 Like