Use_module not importing all predicates

Seems kind of unlikely. This option just adds a clause ‘$derived_source_db’/3 and has no implication on the compiler, module or whatever. A very trivial test doesn’t confirm this either.

Not sure what that means. Considering you load something with derived_from I assume you translate the module to something and then load the derived thing with this option?

Easy to reproduce. Clone the TerminusDB project and then switch to the hub branch. Then (from the clone directory, using the latest SWI-Prolog devel git version):

?- [load_paths].
true.

?- ['core/util'].
true.

?- module_property(util, exported_operators(Operators)).
Operators = [op(601, xfx, @), op(601, xfx, ^^), op(920, fy, *), op(700, xfy, <>)].

?- logtalk_load('core/util').
% [ /Users/pmoura/terminus-server/core/util.pl loaded ]
% (0 warnings)
true.

?- module_property(util, exported_operators(Operators)).
Operators = [].

Halt and then edit the adapters/swi.pl file in your Logtalk installation. Around line 506, in the definition of the '$lgt_load_prolog_code'/3 internal predicate, delete the derived_from/1 option. Repeat the queries above and you get:

?- [load_paths].
true.

?- ['core/util'].
true.

?- module_property(util, exported_operators(Operators)).
Operators = [op(601, xfx, @), op(601, xfx, ^^), op(920, fy, *), op(700, xfy, <>)].

?- logtalk_load('core/util').
% [ /Users/pmoura/terminus-server/core/util.pl loaded ]
% (0 warnings)
true.

?- module_property(util, exported_operators(Operators)).
Operators = [op(601, xfx, @), op(601, xfx, ^^), op(920, fy, *), op(700, xfy, <>)].

I compile the module file. The loaded module itself is not modified in any way.

This seems a bit odd to me. You first load the native Prolog module. Then Logtalk creates some file from it (core/.lgt_tmp/util_10389929_pl.pl) and loads this file telling Prolog that this file was derived from the original file. Apparently if I do not load the Prolog module first, there is no module util. That makes sense as AFAIK loading a Prolog module as a Logtalk object does not use the Prolog module system.

Now the logtalk load will load the tmp file it created as if it was loaded from the original file. That replaces the content of the original file with what is loaded from the logtalk tmp file. As logtalk doesn’t produce the ‘$exported_op’/3 clauses the operators are gone. And probably some more goes wrong by replacing the module by non-module code. I don’t think this will fly.

It helps to understand the scenario here. I’m applying the Logtalk linter to several Prolog projects, including TerminusDB, for testing purposes. To ensure that I can query the module interfaces and get an accurate report, the modules are loaded first (in this particular case, by starting with swilgt start.pl). If the modules are not loaded, I resort to reading the module/2 directive from the module file but this workaround misses exports via export/1 and reexport/1-2 directives.

Correct on both accounts.

The replacement of the content of the original file is not intended or expected. You wrote “This option [derived_from/1] just adds a clause ‘$derived_source_db’/3 and has no implication on the compiler, module or whatever.” Clearly not the case then.

No worries. This is just an artificial testing scenario for the Logtalk linter when applied to Prolog modules. No consequence for actual applications. Thanks for the feedback. One less mystery! :slightly_smiling_face:

Yes and no. The new code is associated with the derived_from file. That indeed is an additional change. This should have no impact, except if you also load something else from that same file. That is the case here.

Something here is still not clear for me. Consider the more detailed output:

?- [load_paths].
true.

?- ['core/util'].
true.

?- module_property(util, Property).
Property = class(user) ;
Property = file('/Users/pmoura/terminus-server/core/util.pl') ;
Property = line_count(1) ;
Property = exports([merge_separator_split/3, is_graph_identifier/1, nonPositiveInteger/3, find/3, is_prefixed_uri/1, integer/3, dateRange/4, ... / ...|...]) ;
Property = exported_operators([op(601, xfx, @), op(601, xfx, ^^), op(920, fy, *), op(700, xfy, <>)]) ;
Property = program_size(2448) ;
Property = last_modified_generation(13676).

?- logtalk_load('core/util').
% [ /Users/pmoura/terminus-server/core/util.pl loaded ]
% (0 warnings)
true.

?- module_property(util, Property).
Property = class(user) ;
Property = file('/Users/pmoura/terminus-server/core/util.pl') ;
Property = line_count(1) ;
Property = exports([merge_separator_split/3, is_graph_identifier/1, nonPositiveInteger/3, find/3, is_prefixed_uri/1, integer/3, dateRange/4, ... / ...|...]) ;
Property = exported_operators([]) ;
Property = program_size(2448) ;
Property = last_modified_generation(13676).

?- current_module(util).
true.

You wrote:

Shouldn’t the other module properties be also affected besides exported_operators/1? The intermediate Prolog file generated by the Logtalk compiler doesn’t define any module. So why is all the other module properties being reported as unchanged? Notably, the list of exported predicates is the same. The argument of the last_modified_generation property is also the same. Moreover, why is the module itself still reported as existing?

Apparently turning a module file into a non-module file using a reload is badly broken. The change generation is probably because this is the last change generation of some predicate in the module and deleting a predicate is not seen as a change (possibly incorrect, but for the scenarios for which I introduced access to the change generations this is fine). I don’t think there is much point in “fixing” this. Surely it will only break your scenarios further. It would be more consistent though, so possibly you would have spotted earlier that this wasn’t going to work.

Modules, except the temporary modules under strict conditions never disappear. One day that may change, but that is fairly hard.

The use by Logtalk of the derived_from/1 option is mainly useful to allow SWI-Prolog make/0 to automatically call Logtalk’s make tool. But this can be easily accomplished in a different way that will not interfere with using the Logtalk linter to check Prolog modules that happen to be loaded. Changed in the git version.

Indeed the fact that only the exported_operators/1 property changed made me think that the issue could be somehow related to the original bug report that started this thread. Btw, any updates on that bug causes and fix?

It seems it doesn’t bother @matthijs any more and I don’ t see much reason to dive into this. There are many more interesting and useful issues.