From: Mark Date: Tue, 19 Mar 2024 23:12:26 +0000 (-0600) Subject: expand_call_goals/3 should expand meta-predicate subgoals (#2361) X-Git-Tag: v0.10.0~151 X-Git-Url: https://git.sagredo.dev/?a=commitdiff_plain;h=0292cb73d37d6b84a38451bff229b6f82d834470;p=scryer-prolog.git expand_call_goals/3 should expand meta-predicate subgoals (#2361) --- diff --git a/src/loader.pl b/src/loader.pl index 4a6fa81e..cdfbf4f9 100644 --- a/src/loader.pl +++ b/src/loader.pl @@ -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 ) ). diff --git a/src/machine/machine_indices.rs b/src/machine/machine_indices.rs index e73611ec..1ae2527b 100644 --- a/src/machine/machine_indices.rs +++ b/src/machine/machine_indices.rs @@ -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( diff --git a/src/machine/system_calls.rs b/src/machine/system_calls.rs index 86d7944a..d884040d 100644 --- a/src/machine/system_calls.rs +++ b/src/machine/system_calls.rs @@ -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 index 00000000..f8c625b2 --- /dev/null +++ b/tests-pl/issue2361-call-qualified.pl @@ -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 index 00000000..aab18e97 --- /dev/null +++ b/tests-pl/issue2361_m.pl @@ -0,0 +1,8 @@ +:- module(m, [gs/1]). + +:- use_module(library(lists)). + +gs([]). +gs([G|Gs]) :- + G, + gs(Gs). diff --git a/tests/scryer/issues.rs b/tests/scryer/issues.rs index 39e30378..556bf9d5 100644 --- a/tests/scryer/issues.rs +++ b/tests/scryer/issues.rs @@ -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", ""); +}