]> Repositorios git - scryer-prolog.git/commitdiff
expand_call_goals/3 should expand meta-predicate subgoals (#2361)
authorMark <[email protected]>
Tue, 19 Mar 2024 23:12:26 +0000 (17:12 -0600)
committerMark <[email protected]>
Tue, 19 Mar 2024 23:12:26 +0000 (17:12 -0600)
src/loader.pl
src/machine/machine_indices.rs
src/machine/system_calls.rs
tests-pl/issue2361-call-qualified.pl [new file with mode: 0644]
tests-pl/issue2361_m.pl [new file with mode: 0644]
tests/scryer/issues.rs

index 4a6fa81ecde7455bd571bbae2de12c63bd7b71e8..cdfbf4f9530e8e352127a554f4b18715ba7a1ced 100644 (file)
@@ -887,7 +887,12 @@ expand_call_goal_(UnexpandedGoals, Module, ExpandedGoals) :-
        UnexpandedGoals = ExpandedGoals
     ;  goal_expansion(UnexpandedGoals, Module, UnexpandedGoals1),
        (  Module \== user ->
-          goal_expansion(UnexpandedGoals1, user, ExpandedGoals)
+          goal_expansion(UnexpandedGoals1, user, Goals),
+          (  predicate_property(Module:Goals, meta_predicate(MetaSpecs0)),
+             MetaSpecs0 =.. [_ | MetaSpecs] ->
+             expand_module_names(Goals, MetaSpecs, Module, ExpandedGoals, HeadVars, TGs)
+          ;  ExpandedGoals = Goals
+          )
        ;  ExpandedGoals = UnexpandedGoals1
        )
     ).
index e73611ec2bfadb7a5087cb694cf3578d937096f6..1ae2527b753577ed6e73aea77771fa77383e944d 100644 (file)
@@ -287,8 +287,25 @@ impl IndexStore {
     }
 
     #[inline(always)]
-    pub(crate) fn goal_expansion_defined(&self, key: PredicateKey) -> bool {
-        self.goal_expansion_indices.contains(&key)
+    pub(crate) fn goal_expansion_defined(&self, key: PredicateKey, module_name: Atom) -> bool {
+        let compilation_target = match module_name {
+            atom!("user") => CompilationTarget::User,
+            _ => CompilationTarget::Module(module_name),
+        };
+
+        match key {
+            _ if self.goal_expansion_indices.contains(&key) => true,
+            _ => self
+                .get_meta_predicate_spec(key.0, key.1, &compilation_target)
+                .map(|meta_specs| {
+                    meta_specs.iter().find(|meta_spec| match meta_spec {
+                        MetaSpec::Colon | MetaSpec::RequiresExpansionWithArgument(_) => true,
+                        _ => false,
+                    })
+                })
+                .map(|meta_spec_opt| meta_spec_opt.is_some())
+                .unwrap_or(false),
+        }
     }
 
     pub(crate) fn get_predicate_skeleton_mut(
index 86d7944a59f9f46d2cb6ec8cb6f4a8b7063b3bbf..d884040d4bee99ce02900e284018f6646c8f364b 100644 (file)
@@ -1339,38 +1339,49 @@ impl Machine {
         let index_cell = index_cell_opt.or_else(|| {
             let is_internal_call = name == atom!("$call") && goal_arity > 0;
 
-            if !is_internal_call && self.indices.goal_expansion_defined((name, arity)) {
-                None
-            } else {
-                if is_internal_call {
-                    debug_assert_eq!(goal.get_tag(), HeapCellValueTag::Str);
-                    goal = self.machine_st.heap[goal.get_value() as usize + 1];
-                    (module_name, goal) = self.machine_st.strip_module(goal, module_name);
+            if !is_internal_call {
+                let module_name = if module_name.get_tag() == HeapCellValueTag::Atom {
+                    cell_as_atom!(module_name)
+                } else {
+                    atom!("user")
+                };
 
-                    if let Some((inner_name, inner_arity)) =
-                        self.machine_st.name_and_arity_from_heap(goal)
-                    {
-                        arity -= goal_arity;
-                        (name, goal_arity) = (inner_name, inner_arity);
-                        arity += goal_arity;
-                    } else {
-                        return None;
-                    }
+                if self
+                    .indices
+                    .goal_expansion_defined((name, arity), module_name)
+                {
+                    return None;
                 }
+            }
 
-                let module_name = if module_name.get_tag() != HeapCellValueTag::Atom {
-                    if let Some(load_context) = self.load_contexts.last() {
-                        load_context.module
-                    } else {
-                        atom!("user")
-                    }
-                } else {
-                    cell_as_atom!(module_name)
-                };
+            if is_internal_call {
+                debug_assert_eq!(goal.get_tag(), HeapCellValueTag::Str);
+                goal = self.machine_st.heap[goal.get_value() as usize + 1];
+                (module_name, goal) = self.machine_st.strip_module(goal, module_name);
 
-                self.indices
-                    .get_predicate_code_index(name, arity, module_name)
+                if let Some((inner_name, inner_arity)) =
+                    self.machine_st.name_and_arity_from_heap(goal)
+                {
+                    arity -= goal_arity;
+                    (name, goal_arity) = (inner_name, inner_arity);
+                    arity += goal_arity;
+                } else {
+                    return None;
+                }
             }
+
+            let module_name = if module_name.get_tag() != HeapCellValueTag::Atom {
+                if let Some(load_context) = self.load_contexts.last() {
+                    load_context.module
+                } else {
+                    atom!("user")
+                }
+            } else {
+                cell_as_atom!(module_name)
+            };
+
+            self.indices
+                .get_predicate_code_index(name, arity, module_name)
         });
 
         if let Some(code_index) = index_cell {
diff --git a/tests-pl/issue2361-call-qualified.pl b/tests-pl/issue2361-call-qualified.pl
new file mode 100644 (file)
index 0000000..f8c625b
--- /dev/null
@@ -0,0 +1,3 @@
+:- use_module(issue2361_m).
+
+:- initialization(gs([(length("a",_),length("ab",_))])).
diff --git a/tests-pl/issue2361_m.pl b/tests-pl/issue2361_m.pl
new file mode 100644 (file)
index 0000000..aab18e9
--- /dev/null
@@ -0,0 +1,8 @@
+:- module(m, [gs/1]).
+
+:- use_module(library(lists)).
+
+gs([]).
+gs([G|Gs]) :-
+        G,
+        gs(Gs).
index 39e303780241cc0fea28cc2368e1bedbc145a9bd..556bf9d5b21dbfa047021ecfaa2e0ff4851f3e1f 100644 (file)
@@ -11,3 +11,10 @@ fn call_0() {
         "   error(existence_error(procedure,call/0),call/0).\n",
     );
 }
+
+// issue #2361
+#[serial]
+#[test]
+fn call_qualification() {
+    load_module_test("tests-pl/issue2361-call-qualified.pl", "");
+}