Merge pull request #1885 from mthom/setof_bagof_fixes
Fix group_by_variants/4 and keysort in setof/3
This commit is contained in:
@@ -141,7 +141,7 @@ impl MachineState {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn keysort(&mut self) -> CallResult {
|
||||
fn keysort(&mut self, var_comparison: VarComparison) -> CallResult {
|
||||
self.check_keysort_errors()?;
|
||||
|
||||
let stub_gen = || functor_stub(atom!("keysort"), 2);
|
||||
@@ -155,7 +155,7 @@ impl MachineState {
|
||||
}
|
||||
|
||||
key_pairs.sort_by(|a1, a2| {
|
||||
compare_term_test!(self, a1.0, a2.0).unwrap_or(Ordering::Less)
|
||||
compare_term_test!(self, a1.0, a2.0, var_comparison).unwrap_or(Ordering::Less)
|
||||
});
|
||||
|
||||
let key_pairs = key_pairs.into_iter().map(|kp| kp.1);
|
||||
@@ -1396,11 +1396,11 @@ impl Machine {
|
||||
step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
|
||||
}
|
||||
&Instruction::DefaultCallKeySort => {
|
||||
try_or_throw!(self.machine_st, self.machine_st.keysort());
|
||||
try_or_throw!(self.machine_st, self.machine_st.keysort(VarComparison::Distinct));
|
||||
step_or_fail!(self, self.machine_st.p += 1);
|
||||
}
|
||||
&Instruction::DefaultExecuteKeySort => {
|
||||
try_or_throw!(self.machine_st, self.machine_st.keysort());
|
||||
try_or_throw!(self.machine_st, self.machine_st.keysort(VarComparison::Distinct));
|
||||
|
||||
if self.machine_st.fail {
|
||||
self.machine_st.backtrack();
|
||||
@@ -1801,7 +1801,7 @@ impl Machine {
|
||||
}
|
||||
}
|
||||
&Instruction::CallKeySort => {
|
||||
try_or_throw!(self.machine_st, self.machine_st.keysort());
|
||||
try_or_throw!(self.machine_st, self.machine_st.keysort(VarComparison::Distinct));
|
||||
|
||||
if self.machine_st.fail {
|
||||
self.machine_st.backtrack();
|
||||
@@ -1815,7 +1815,35 @@ impl Machine {
|
||||
}
|
||||
}
|
||||
&Instruction::ExecuteKeySort => {
|
||||
try_or_throw!(self.machine_st, self.machine_st.keysort());
|
||||
try_or_throw!(self.machine_st, self.machine_st.keysort(VarComparison::Distinct));
|
||||
|
||||
if self.machine_st.fail {
|
||||
self.machine_st.backtrack();
|
||||
} else {
|
||||
try_or_throw!(
|
||||
self.machine_st,
|
||||
(self.machine_st.increment_call_count_fn)(&mut self.machine_st)
|
||||
);
|
||||
|
||||
self.machine_st.p = self.machine_st.cp;
|
||||
}
|
||||
}
|
||||
&Instruction::CallKeySortWithConstantVarOrdering => {
|
||||
try_or_throw!(self.machine_st, self.machine_st.keysort(VarComparison::Indistinct));
|
||||
|
||||
if self.machine_st.fail {
|
||||
self.machine_st.backtrack();
|
||||
} else {
|
||||
try_or_throw!(
|
||||
self.machine_st,
|
||||
(self.machine_st.increment_call_count_fn)(&mut self.machine_st)
|
||||
);
|
||||
|
||||
self.machine_st.p += 1;
|
||||
}
|
||||
}
|
||||
&Instruction::ExecuteKeySortWithConstantVarOrdering => {
|
||||
try_or_throw!(self.machine_st, self.machine_st.keysort(VarComparison::Indistinct));
|
||||
|
||||
if self.machine_st.fail {
|
||||
self.machine_st.backtrack();
|
||||
@@ -4097,6 +4125,14 @@ impl Machine {
|
||||
self.get_double_quotes();
|
||||
step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
|
||||
}
|
||||
&Instruction::CallGetUnknown => {
|
||||
self.get_unknown();
|
||||
step_or_fail!(self, self.machine_st.p += 1);
|
||||
}
|
||||
&Instruction::ExecuteGetUnknown => {
|
||||
self.get_unknown();
|
||||
step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
|
||||
}
|
||||
&Instruction::CallInstallNewBlock => {
|
||||
self.machine_st.install_new_block(self.machine_st.registers[1]);
|
||||
step_or_fail!(self, self.machine_st.p += 1);
|
||||
@@ -4285,6 +4321,14 @@ impl Machine {
|
||||
self.set_double_quotes();
|
||||
step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
|
||||
}
|
||||
&Instruction::CallSetUnknown => {
|
||||
self.set_unknown();
|
||||
step_or_fail!(self, self.machine_st.p += 1);
|
||||
}
|
||||
&Instruction::ExecuteSetUnknown => {
|
||||
self.set_unknown();
|
||||
step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
|
||||
}
|
||||
&Instruction::CallSetSeed => {
|
||||
self.set_seed();
|
||||
step_or_fail!(self, self.machine_st.p += 1);
|
||||
|
||||
@@ -435,7 +435,7 @@ impl MachineState {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn compare_term_test(&mut self) -> Option<Ordering> {
|
||||
pub fn compare_term_test(&mut self, var_comparison: VarComparison) -> Option<Ordering> {
|
||||
let mut tabu_list = IndexSet::new();
|
||||
|
||||
while !self.pdl.is_empty() {
|
||||
@@ -462,12 +462,14 @@ impl MachineState {
|
||||
|
||||
match order_cat_v1 {
|
||||
Some(TermOrderCategory::Variable) => {
|
||||
let v1 = v1.as_var().unwrap();
|
||||
let v2 = v2.as_var().unwrap();
|
||||
if let VarComparison::Distinct = var_comparison {
|
||||
let v1 = v1.as_var().unwrap();
|
||||
let v2 = v2.as_var().unwrap();
|
||||
|
||||
if v1 != v2 {
|
||||
self.pdl.clear();
|
||||
return Some(v1.cmp(&v2));
|
||||
if v1 != v2 {
|
||||
self.pdl.clear();
|
||||
return Some(v1.cmp(&v2));
|
||||
}
|
||||
}
|
||||
}
|
||||
Some(TermOrderCategory::FloatingPoint) => {
|
||||
|
||||
@@ -1026,6 +1026,24 @@ impl Machine {
|
||||
self.machine_st.heap.truncate(target_h);
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn undefined_procedure(&mut self, name: Atom, arity: usize) -> CallResult {
|
||||
match self.machine_st.flags.unknown {
|
||||
Unknown::Error => {
|
||||
Err(self.machine_st.throw_undefined_error(name, arity))
|
||||
}
|
||||
Unknown::Fail => {
|
||||
self.machine_st.fail = true;
|
||||
Ok(())
|
||||
}
|
||||
Unknown::Warn => {
|
||||
println!("warning: predicate {}/{} is undefined", name.as_str(), arity);
|
||||
self.machine_st.fail = true;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn try_call(&mut self, name: Atom, arity: usize, idx: IndexPtr) -> CallResult {
|
||||
let compiled_tl_index = idx.p() as usize;
|
||||
@@ -1035,7 +1053,7 @@ impl Machine {
|
||||
self.machine_st.fail = true;
|
||||
}
|
||||
IndexPtrTag::Undefined => {
|
||||
return Err(self.machine_st.throw_undefined_error(name, arity));
|
||||
return self.undefined_procedure(name, arity);
|
||||
}
|
||||
IndexPtrTag::DynamicIndex => {
|
||||
self.machine_st.dynamic_mode = FirstOrNext::First;
|
||||
@@ -1058,7 +1076,7 @@ impl Machine {
|
||||
self.machine_st.fail = true;
|
||||
}
|
||||
IndexPtrTag::Undefined => {
|
||||
return Err(self.machine_st.throw_undefined_error(name, arity));
|
||||
return self.undefined_procedure(name, arity);
|
||||
}
|
||||
IndexPtrTag::DynamicIndex => {
|
||||
self.machine_st.dynamic_mode = FirstOrNext::First;
|
||||
@@ -1087,7 +1105,7 @@ impl Machine {
|
||||
if let Some(idx) = module.code_dir.get(&(name, arity)).cloned() {
|
||||
self.try_call(name, arity, idx.get())
|
||||
} else {
|
||||
Err(self.machine_st.throw_undefined_error(name, arity))
|
||||
self.undefined_procedure(name, arity)
|
||||
}
|
||||
} else {
|
||||
let stub = functor_stub(name, arity);
|
||||
@@ -1106,14 +1124,14 @@ impl Machine {
|
||||
if let Some(idx) = self.indices.code_dir.get(&(name, arity)).cloned() {
|
||||
self.try_execute(name, arity, idx.get())
|
||||
} else {
|
||||
Err(self.machine_st.throw_undefined_error(name, arity))
|
||||
self.undefined_procedure(name, arity)
|
||||
}
|
||||
} else {
|
||||
if let Some(module) = self.indices.modules.get(&module_name) {
|
||||
if let Some(idx) = module.code_dir.get(&(name, arity)).cloned() {
|
||||
self.try_execute(name, arity, idx.get())
|
||||
} else {
|
||||
Err(self.machine_st.throw_undefined_error(name, arity))
|
||||
self.undefined_procedure(name, arity)
|
||||
}
|
||||
} else {
|
||||
let stub = functor_stub(name, arity);
|
||||
|
||||
@@ -5192,6 +5192,20 @@ impl Machine {
|
||||
);
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub(crate) fn get_unknown(&mut self) {
|
||||
let a1 = self.deref_register(1);
|
||||
|
||||
self.machine_st.unify_atom(
|
||||
match self.machine_st.flags.unknown {
|
||||
Unknown::Error => atom!("error"),
|
||||
Unknown::Fail => atom!("fail"),
|
||||
Unknown::Warn => atom!("warning"),
|
||||
},
|
||||
a1,
|
||||
);
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub(crate) fn get_scc_cleaner(&mut self) {
|
||||
let dest = self.machine_st.registers[1];
|
||||
@@ -5534,7 +5548,7 @@ impl Machine {
|
||||
|
||||
#[inline(always)]
|
||||
pub(crate) fn set_double_quotes(&mut self) {
|
||||
let atom = cell_as_atom!(self.machine_st.registers[1]);
|
||||
let atom = cell_as_atom!(self.deref_register(1));
|
||||
|
||||
self.machine_st.flags.double_quotes = match atom {
|
||||
atom!("atom") => DoubleQuotes::Atom,
|
||||
@@ -5547,6 +5561,21 @@ impl Machine {
|
||||
};
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub(crate) fn set_unknown(&mut self) {
|
||||
let atom = cell_as_atom!(self.deref_register(1));
|
||||
|
||||
self.machine_st.flags.unknown = match atom {
|
||||
atom!("error") => Unknown::Error,
|
||||
atom!("fail") => Unknown::Fail,
|
||||
atom!("warning") => Unknown::Warn,
|
||||
_ => {
|
||||
self.machine_st.fail = true;
|
||||
return;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub(crate) fn inference_level(&mut self) {
|
||||
let a1 = self.deref_register(1);
|
||||
|
||||
Reference in New Issue
Block a user