fix bugs in call_with_inference_limit
This commit is contained in:
@@ -892,7 +892,7 @@ pub enum BuiltInInstruction {
|
|||||||
GetBall,
|
GetBall,
|
||||||
GetCurrentBlock,
|
GetCurrentBlock,
|
||||||
GetCutPoint(RegType),
|
GetCutPoint(RegType),
|
||||||
InferenceLevel,
|
InferenceLevel(RegType, RegType),
|
||||||
InstallCleaner,
|
InstallCleaner,
|
||||||
InstallInferenceCounter(RegType, RegType, RegType),
|
InstallInferenceCounter(RegType, RegType, RegType),
|
||||||
InstallNewBlock,
|
InstallNewBlock,
|
||||||
|
|||||||
@@ -565,37 +565,37 @@ fn get_builtins(atom_tbl: TabledData<Atom>) -> Code {
|
|||||||
deallocate!(),
|
deallocate!(),
|
||||||
remove_call_policy_check!(),
|
remove_call_policy_check!(),
|
||||||
proceed!(),
|
proceed!(),
|
||||||
try_me_else!(18), // call_with_inference_limit/5, 404.
|
try_me_else!(19), // call_with_inference_limit/5, 404.
|
||||||
allocate!(9),
|
allocate!(9),
|
||||||
fact![get_var_in_fact!(perm_v!(9), 1),
|
fact![get_var_in_fact!(perm_v!(9), 1),
|
||||||
get_var_in_fact!(perm_v!(6), 2),
|
get_var_in_fact!(perm_v!(5), 2),
|
||||||
get_var_in_fact!(perm_v!(5), 3),
|
get_var_in_fact!(perm_v!(8), 3),
|
||||||
get_var_in_fact!(perm_v!(3), 4),
|
get_var_in_fact!(perm_v!(3), 4),
|
||||||
get_var_in_fact!(perm_v!(4), 5)],
|
get_var_in_fact!(perm_v!(4), 5)],
|
||||||
query![put_var!(perm_v!(1), 1)],
|
query![put_var!(perm_v!(1), 1)],
|
||||||
install_new_block!(),
|
install_new_block!(),
|
||||||
install_inference_counter!(perm_v!(4), perm_v!(6), perm_v!(8)),
|
query![put_var!(perm_v!(7), 3)],
|
||||||
|
install_inference_counter!(perm_v!(4), perm_v!(5), perm_v!(7)),
|
||||||
query![put_value!(perm_v!(9), 1)],
|
query![put_value!(perm_v!(9), 1)],
|
||||||
call_n!(1),
|
call_n!(1),
|
||||||
remove_inference_counter!(perm_v!(4), perm_v!(7)),
|
inference_level!(perm_v!(8), perm_v!(4)),
|
||||||
sub!(ArithmeticTerm::Reg(perm_v!(7)),
|
query![put_var!(perm_v!(6), 2)],
|
||||||
ArithmeticTerm::Reg(perm_v!(8)),
|
remove_inference_counter!(perm_v!(4), perm_v!(6)),
|
||||||
1),
|
|
||||||
sub!(ArithmeticTerm::Reg(perm_v!(6)),
|
sub!(ArithmeticTerm::Reg(perm_v!(6)),
|
||||||
|
ArithmeticTerm::Reg(perm_v!(7)),
|
||||||
|
1),
|
||||||
|
sub!(ArithmeticTerm::Reg(perm_v!(5)),
|
||||||
ArithmeticTerm::Interm(1),
|
ArithmeticTerm::Interm(1),
|
||||||
1),
|
1),
|
||||||
query![put_value!(perm_v!(2), 1)],
|
query![put_var!(perm_v!(2), 1)],
|
||||||
is_call!(temp_v!(1), ArithmeticTerm::Interm(1)),
|
is_call!(temp_v!(1), ArithmeticTerm::Interm(1)),
|
||||||
query![put_value!(perm_v!(5), 1),
|
|
||||||
put_value!(perm_v!(4), 2)],
|
|
||||||
inference_level!(),
|
|
||||||
query![put_value!(perm_v!(4), 1),
|
query![put_value!(perm_v!(4), 1),
|
||||||
put_value!(perm_v!(3), 2),
|
put_value!(perm_v!(3), 2),
|
||||||
put_value!(perm_v!(1), 3),
|
put_value!(perm_v!(1), 3),
|
||||||
put_value!(perm_v!(2), 4)],
|
put_value!(perm_v!(2), 4)],
|
||||||
deallocate!(),
|
deallocate!(),
|
||||||
goto_execute!(442, 4), // goto end_block/4, 442.
|
goto_execute!(452, 4), // goto end_block/4, 452
|
||||||
default_trust_me!(), // 422.
|
default_trust_me!(), // 423
|
||||||
allocate!(3),
|
allocate!(3),
|
||||||
fact![get_var_in_fact!(perm_v!(1), 3),
|
fact![get_var_in_fact!(perm_v!(1), 3),
|
||||||
get_var_in_fact!(perm_v!(3), 5)],
|
get_var_in_fact!(perm_v!(3), 5)],
|
||||||
@@ -603,37 +603,48 @@ fn get_builtins(atom_tbl: TabledData<Atom>) -> Code {
|
|||||||
reset_block!(),
|
reset_block!(),
|
||||||
query![put_var!(temp_v!(3), 2)],
|
query![put_var!(temp_v!(3), 2)],
|
||||||
remove_inference_counter!(perm_v!(3), temp_v!(2)),
|
remove_inference_counter!(perm_v!(3), temp_v!(2)),
|
||||||
query![put_var!(perm_v!(2), 1)],
|
query![put_value!(perm_v!(3), 1),
|
||||||
get_ball!(),
|
put_var!(perm_v!(2), 2)],
|
||||||
|
jmp_call!(2, 5),
|
||||||
erase_ball!(),
|
erase_ball!(),
|
||||||
query![put_value!(perm_v!(3), 1),
|
query![put_value!(perm_v!(3), 1),
|
||||||
put_unsafe_value!(2, 2),
|
put_unsafe_value!(2, 2),
|
||||||
put_value!(perm_v!(1), 3)],
|
put_value!(perm_v!(1), 3)],
|
||||||
deallocate!(),
|
deallocate!(),
|
||||||
goto_execute!(435, 3), // goto handle_ile/3, 435.
|
goto_execute!(444, 3), // goto handle_ile/3, 442.
|
||||||
try_me_else!(4), // handle_ile/3, 435.
|
try_me_else!(5), // the inner clause.
|
||||||
|
query![put_value!(temp_v!(2), 1)],
|
||||||
|
get_ball!(),
|
||||||
|
neck_cut!(),
|
||||||
|
proceed!(),
|
||||||
|
default_trust_me!(),
|
||||||
|
remove_call_policy_check!(),
|
||||||
|
fail!(),
|
||||||
|
try_me_else!(4), // handle_ile/3, 444.
|
||||||
fact![get_structure!(atom_tbl, "inference_limit_exceeded", 1, temp_v!(2), None),
|
fact![get_structure!(atom_tbl, "inference_limit_exceeded", 1, temp_v!(2), None),
|
||||||
unify_value!(temp_v!(1)),
|
unify_value!(temp_v!(1)),
|
||||||
get_constant!(atom!("inference_limit_exceeded", atom_tbl), temp_v!(3))],
|
get_constant!(atom!("inference_limit_exceeded", atom_tbl), temp_v!(3))],
|
||||||
neck_cut!(),
|
neck_cut!(),
|
||||||
proceed!(),
|
proceed!(),
|
||||||
default_trust_me!(),
|
default_trust_me!(),
|
||||||
|
remove_call_policy_check!(),
|
||||||
query![put_value!(temp_v!(2), 1)],
|
query![put_value!(temp_v!(2), 1)],
|
||||||
goto_execute!(59, 1), // goto throw/1, 59.
|
goto_execute!(59, 1), // goto throw/1, 59.
|
||||||
try_me_else!(6), // end_block/4, 442.
|
try_me_else!(6), // end_block/4, 452.
|
||||||
query![put_value!(temp_v!(3), 1)],
|
query![put_value!(temp_v!(3), 1)],
|
||||||
clean_up_block!(),
|
clean_up_block!(),
|
||||||
query![put_value!(temp_v!(2), 1)],
|
query![put_value!(temp_v!(2), 1)],
|
||||||
reset_block!(),
|
reset_block!(),
|
||||||
proceed!(),
|
proceed!(),
|
||||||
default_trust_me!(),
|
default_trust_me!(),
|
||||||
query![put_value!(temp_v!(4), 2),
|
query![get_var_in_query!(temp_v!(5), 3),
|
||||||
put_var!(temp_v!(4), 4)],
|
put_value!(temp_v!(4), 2),
|
||||||
install_inference_counter!(temp_v!(1), temp_v!(2), temp_v!(4)),
|
put_var!(temp_v!(6), 3)],
|
||||||
query![put_value!(temp_v!(3), 1)],
|
install_inference_counter!(temp_v!(1), temp_v!(4), temp_v!(6)),
|
||||||
|
query![put_value!(temp_v!(5), 1)],
|
||||||
reset_block!(),
|
reset_block!(),
|
||||||
fail!(),
|
fail!(),
|
||||||
compare_execute!() // compare/3, 454.
|
compare_execute!() // compare/3, 464.
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -749,7 +760,7 @@ pub fn build_code_dir(atom_tbl: TabledData<Atom>) -> (Code, CodeDir, OpDir)
|
|||||||
code_dir.insert((tabled_rc!("@<", atom_tbl), 2), (PredicateKeyType::BuiltIn, 390));
|
code_dir.insert((tabled_rc!("@<", atom_tbl), 2), (PredicateKeyType::BuiltIn, 390));
|
||||||
code_dir.insert((tabled_rc!("=@=", atom_tbl), 2), (PredicateKeyType::BuiltIn, 391));
|
code_dir.insert((tabled_rc!("=@=", atom_tbl), 2), (PredicateKeyType::BuiltIn, 391));
|
||||||
code_dir.insert((tabled_rc!("\\=@=", atom_tbl), 2), (PredicateKeyType::BuiltIn, 392));
|
code_dir.insert((tabled_rc!("\\=@=", atom_tbl), 2), (PredicateKeyType::BuiltIn, 392));
|
||||||
code_dir.insert((tabled_rc!("compare", atom_tbl), 3), (PredicateKeyType::BuiltIn, 454));
|
code_dir.insert((tabled_rc!("compare", atom_tbl), 3), (PredicateKeyType::BuiltIn, 464));
|
||||||
|
|
||||||
(builtin_code, code_dir, op_dir)
|
(builtin_code, code_dir, op_dir)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -229,8 +229,8 @@ impl fmt::Display for BuiltInInstruction {
|
|||||||
write!(f, "get_current_block X1"),
|
write!(f, "get_current_block X1"),
|
||||||
&BuiltInInstruction::GetCutPoint(r) =>
|
&BuiltInInstruction::GetCutPoint(r) =>
|
||||||
write!(f, "get_cp {}", r),
|
write!(f, "get_cp {}", r),
|
||||||
&BuiltInInstruction::InferenceLevel =>
|
&BuiltInInstruction::InferenceLevel(r1, r2) =>
|
||||||
write!(f, "inference_level"),
|
write!(f, "inference_level {}, {}", r1, r2),
|
||||||
&BuiltInInstruction::InstallCleaner =>
|
&BuiltInInstruction::InstallCleaner =>
|
||||||
write!(f, "install_cleaner"),
|
write!(f, "install_cleaner"),
|
||||||
&BuiltInInstruction::InstallNewBlock =>
|
&BuiltInInstruction::InstallNewBlock =>
|
||||||
|
|||||||
@@ -370,7 +370,7 @@ impl CallWithInferenceLimitCallPolicy {
|
|||||||
*policy = Box::new(new_policy);
|
*policy = Box::new(new_policy);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn increment(&mut self) -> CallResult {
|
fn increment(&mut self) -> CallResult {
|
||||||
if let Some(&(ref limit, bp)) = self.limits.last() {
|
if let Some(&(ref limit, bp)) = self.limits.last() {
|
||||||
if self.count == **limit {
|
if self.count == **limit {
|
||||||
return Err(functor!(self.atom_tbl,
|
return Err(functor!(self.atom_tbl,
|
||||||
@@ -385,7 +385,6 @@ impl CallWithInferenceLimitCallPolicy {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
// returns the count.
|
|
||||||
pub(crate) fn add_limit(&mut self, limit: Rc<BigInt>, b: usize) -> Rc<BigInt> {
|
pub(crate) fn add_limit(&mut self, limit: Rc<BigInt>, b: usize) -> Rc<BigInt> {
|
||||||
let limit = Rc::new(&*limit + &self.count);
|
let limit = Rc::new(&*limit + &self.count);
|
||||||
|
|
||||||
@@ -397,7 +396,6 @@ impl CallWithInferenceLimitCallPolicy {
|
|||||||
Rc::new(self.count.clone())
|
Rc::new(self.count.clone())
|
||||||
}
|
}
|
||||||
|
|
||||||
// returns the count.
|
|
||||||
pub(crate) fn remove_limit(&mut self, b: usize) -> Rc<BigInt> {
|
pub(crate) fn remove_limit(&mut self, b: usize) -> Rc<BigInt> {
|
||||||
if let Some((_, bp)) = self.limits.last().cloned() {
|
if let Some((_, bp)) = self.limits.last().cloned() {
|
||||||
if bp == b {
|
if bp == b {
|
||||||
|
|||||||
@@ -216,6 +216,7 @@ impl MachineState {
|
|||||||
let tr = self.tr;
|
let tr = self.tr;
|
||||||
let val = self.trail[tr - 1];
|
let val = self.trail[tr - 1];
|
||||||
self.trail[i] = val;
|
self.trail[i] = val;
|
||||||
|
self.tr -= 1; // NEW.
|
||||||
},
|
},
|
||||||
Ref::StackCell(fr, _) => {
|
Ref::StackCell(fr, _) => {
|
||||||
let b = self.b - 1;
|
let b = self.b - 1;
|
||||||
@@ -232,6 +233,7 @@ impl MachineState {
|
|||||||
let tr = self.tr;
|
let tr = self.tr;
|
||||||
let val = self.trail[tr - 1];
|
let val = self.trail[tr - 1];
|
||||||
self.trail[i] = val;
|
self.trail[i] = val;
|
||||||
|
self.tr -= 1; // NEW.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -1313,9 +1315,9 @@ impl MachineState {
|
|||||||
|
|
||||||
self.p += 1;
|
self.p += 1;
|
||||||
},
|
},
|
||||||
&BuiltInInstruction::InferenceLevel => { // X1 = R, X2 = B.
|
&BuiltInInstruction::InferenceLevel(r1, r2) => { // X1 = R, X2 = B.
|
||||||
let a1 = self[temp_v!(1)].clone();
|
let a1 = self[r1].clone();
|
||||||
let a2 = self.store(self.deref(self[temp_v!(2)].clone()));
|
let a2 = self.store(self.deref(self[r2].clone()));
|
||||||
|
|
||||||
match a2 {
|
match a2 {
|
||||||
Addr::Con(Constant::Usize(bp)) =>
|
Addr::Con(Constant::Usize(bp)) =>
|
||||||
@@ -1366,7 +1368,7 @@ impl MachineState {
|
|||||||
match call_policy.downcast_mut::<CallWithInferenceLimitCallPolicy>().ok() {
|
match call_policy.downcast_mut::<CallWithInferenceLimitCallPolicy>().ok() {
|
||||||
Some(call_policy) => {
|
Some(call_policy) => {
|
||||||
let count = call_policy.add_limit(n, bp);
|
let count = call_policy.add_limit(n, bp);
|
||||||
self[r3] = Addr::Con(Constant::Number(Number::Integer(count)));
|
self[r3] = Addr::Con(Constant::Number(Number::Integer(count)));
|
||||||
},
|
},
|
||||||
None => panic!("install_inference_counter: should have installed \\
|
None => panic!("install_inference_counter: should have installed \\
|
||||||
CallWithInferenceLimitCallPolicy.")
|
CallWithInferenceLimitCallPolicy.")
|
||||||
@@ -1457,10 +1459,10 @@ impl MachineState {
|
|||||||
None
|
None
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
panic!("remove_inference_counter: expected Usize in A1.");
|
panic!("remove_call_policy_check: expected Usize in A1.");
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
None => panic!("remove_inference_counters: requires \\
|
None => panic!("remove_call_policy_check: requires \\
|
||||||
CallWithInferenceLimitCallPolicy.")
|
CallWithInferenceLimitCallPolicy.")
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1470,15 +1472,14 @@ impl MachineState {
|
|||||||
|
|
||||||
self.p += 1;
|
self.p += 1;
|
||||||
},
|
},
|
||||||
&BuiltInInstruction::RemoveInferenceCounter(r1, r2) => { // A1 = B, A2 = Count.
|
&BuiltInInstruction::RemoveInferenceCounter(r1, r2) => { // A1 = B
|
||||||
match call_policy.downcast_mut::<CallWithInferenceLimitCallPolicy>().ok() {
|
match call_policy.downcast_mut::<CallWithInferenceLimitCallPolicy>().ok() {
|
||||||
Some(call_policy) => {
|
Some(call_policy) => {
|
||||||
let a1 = self.store(self.deref(self[r1].clone()));
|
let a1 = self.store(self.deref(self[r1].clone()));
|
||||||
|
|
||||||
if let Addr::Con(Constant::Usize(bp)) = a1 {
|
if let Addr::Con(Constant::Usize(bp)) = a1 {
|
||||||
let count = call_policy.remove_limit(bp);
|
let count = call_policy.remove_limit(bp);
|
||||||
self[r2] = Addr::Con(Constant::Number(Number::Integer(count)));
|
self[r2] = Addr::Con(Constant::Number(Number::Integer(count)));
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
panic!("remove_inference_counter: expected Usize in A1.");
|
panic!("remove_inference_counter: expected Usize in A1.");
|
||||||
}
|
}
|
||||||
@@ -1844,9 +1845,9 @@ impl MachineState {
|
|||||||
Ordering::Equal => atom!("=", self.atom_tbl),
|
Ordering::Equal => atom!("=", self.atom_tbl),
|
||||||
Ordering::Less => atom!("<", self.atom_tbl)
|
Ordering::Less => atom!("<", self.atom_tbl)
|
||||||
});
|
});
|
||||||
|
|
||||||
self.unify(a1, c);
|
self.unify(a1, c);
|
||||||
|
|
||||||
self.p += 1;
|
self.p += 1;
|
||||||
},
|
},
|
||||||
&ControlInstruction::CompareExecute => {
|
&ControlInstruction::CompareExecute => {
|
||||||
@@ -1859,9 +1860,9 @@ impl MachineState {
|
|||||||
Ordering::Equal => atom!("=", self.atom_tbl),
|
Ordering::Equal => atom!("=", self.atom_tbl),
|
||||||
Ordering::Less => atom!("<", self.atom_tbl)
|
Ordering::Less => atom!("<", self.atom_tbl)
|
||||||
});
|
});
|
||||||
|
|
||||||
self.unify(a1, c);
|
self.unify(a1, c);
|
||||||
|
|
||||||
self.p = self.cp;
|
self.p = self.cp;
|
||||||
},
|
},
|
||||||
&ControlInstruction::CompareTermCall(qt) => {
|
&ControlInstruction::CompareTermCall(qt) => {
|
||||||
|
|||||||
@@ -642,8 +642,8 @@ macro_rules! remove_inference_counter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! inference_level {
|
macro_rules! inference_level {
|
||||||
() => (
|
($r1:expr, $r2:expr) => (
|
||||||
Line::BuiltIn(BuiltInInstruction::InferenceLevel)
|
Line::BuiltIn(BuiltInInstruction::InferenceLevel($r1, $r2))
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
11
src/tests.rs
11
src/tests.rs
@@ -1451,9 +1451,7 @@ fn test_queries_on_call_with_inference_limit()
|
|||||||
|
|
||||||
assert_prolog_success!(&mut wam, "?- call_with_inference_limit(throw(error), 0, R).",
|
assert_prolog_success!(&mut wam, "?- call_with_inference_limit(throw(error), 0, R).",
|
||||||
[["R = inference_limit_exceeded"]]);
|
[["R = inference_limit_exceeded"]]);
|
||||||
assert_prolog_success!(&mut wam, "?- catch(call_with_inference_limit(throw(error), 1, R),
|
assert_prolog_success!(&mut wam, "?- catch(call_with_inference_limit(throw(error), 1, R), error, true).");
|
||||||
error,
|
|
||||||
true).");
|
|
||||||
|
|
||||||
assert_prolog_failure!(&mut wam, "?- call_with_inference_limit(g(X), 5, R).");
|
assert_prolog_failure!(&mut wam, "?- call_with_inference_limit(g(X), 5, R).");
|
||||||
|
|
||||||
@@ -1475,6 +1473,13 @@ fn test_queries_on_call_with_inference_limit()
|
|||||||
[["R = true", "X = 1"],
|
[["R = true", "X = 1"],
|
||||||
["R = true", "X = 2"],
|
["R = true", "X = 2"],
|
||||||
["R = inference_limit_exceeded", "X = _1"]]);
|
["R = inference_limit_exceeded", "X = _1"]]);
|
||||||
|
assert_prolog_success!(&mut wam, "?- call_with_inference_limit(g(X), 3, R1),
|
||||||
|
call_with_inference_limit(g(X), 5, R2).",
|
||||||
|
[["X = 1", "R1 = true", "R2 = !"],
|
||||||
|
["X = 2", "R1 = true", "R2 = !"],
|
||||||
|
["X = 3", "R1 = true", "R2 = !"],
|
||||||
|
["X = 4", "R1 = true", "R2 = !"],
|
||||||
|
["X = 5", "R1 = !", "R2 = !"]]);
|
||||||
|
|
||||||
submit(&mut wam, "f(X) :- call_with_inference_limit(g(X), 5, _).");
|
submit(&mut wam, "f(X) :- call_with_inference_limit(g(X), 5, _).");
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user