Fix #2725 by calling load_context/1 in the unspecified branch of strip_module/3

This fixes #2725, by making it so that `strip_module(Pred, M, P), call(M:P)`
doesn't throw an `instanciation_error` when `Pred` isn't in the form `module:predicate`.

Now, `strip_module(hello, M, P)` will call `load_context(M)`, which unifies `M`
with the topmost module (or `user`).

Two new test cases are added: issue2725.pl, which tests the minimal case id(X) --> X.
and the strip_module(P, M, _), call(M:P) scenario, and module_resolution,
which tests the behavior of strip_module in a few scenarios.
This commit is contained in:
Emilie Burgun
2025-01-01 17:27:40 +01:00
parent 1ed4fe6555
commit b76bdd75e4
9 changed files with 88 additions and 14 deletions

View File

@@ -104,6 +104,22 @@ use super::libraries;
use super::preprocessor::to_op_decl;
use super::preprocessor::to_op_decl_spec;
/// Represents the presence (or absence) of a `module:` prefix to predicates, used to
/// refer to predicates defined in a given `module` that haven't been imported
/// (through `use_module/1`) or exported.
///
/// On the Rust side, [`MachineState::strip_module`] splits a given [`HeapCellValue`] into
/// a pair of [`ModuleQuantification`] and `HeapCellValue`.
///
/// On the Prolog side, `strip_module(X, Y, Z)` is a wrapper around [`MachineState::strip_module`],
/// which takes care of splitting the `X = module:predicate` pair into `Y = module` and
/// `Z = predicate`. If no module prefix is present (ie. [`MachineState::strip_module`] returned
/// `Unspecified`), then `strip_module/3` calls `load_context(Y)`, unifying `Y` with the currently
/// loaded module (or `user`).
///
/// [`Machine::quantification_to_module_name`] provides a similar mechanism on the Rust side to
/// obtain the currently loaded module in the `Unspecified` case.
/// It also defaults to `user`, for instance if we are in the REPL.
#[derive(Debug)]
pub(crate) enum ModuleQuantification {
Specified(HeapCellValue),