Skip to content

Commit

Permalink
expand_call_goals/3 should expand meta-predicate subgoals (#2361)
Browse files Browse the repository at this point in the history
  • Loading branch information
mthom committed Mar 19, 2024
1 parent 7b33eaf commit 0292cb7
Show file tree
Hide file tree
Showing 6 changed files with 81 additions and 30 deletions.
7 changes: 6 additions & 1 deletion src/loader.pl
Original file line number Diff line number Diff line change
Expand Up @@ -887,7 +887,12 @@
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
)
).
Expand Down
21 changes: 19 additions & 2 deletions src/machine/machine_indices.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down
65 changes: 38 additions & 27 deletions src/machine/system_calls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
3 changes: 3 additions & 0 deletions tests-pl/issue2361-call-qualified.pl
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
:- use_module(issue2361_m).

:- initialization(gs([(length("a",_),length("ab",_))])).
8 changes: 8 additions & 0 deletions tests-pl/issue2361_m.pl
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
:- module(m, [gs/1]).

:- use_module(library(lists)).

gs([]).
gs([G|Gs]) :-
G,
gs(Gs).
7 changes: 7 additions & 0 deletions tests/scryer/issues.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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", "");
}

0 comments on commit 0292cb7

Please sign in to comment.