fix bugs in call_with_inference_limit

This commit is contained in:
Mark Thom
2018-02-21 19:46:15 -07:00
parent 7313472a70
commit 5de03444eb
13 changed files with 248 additions and 201 deletions

View File

@@ -6,13 +6,14 @@ mod prolog;
#[macro_use] mod test_utils; #[macro_use] mod test_utils;
use prolog::io::*; use prolog::io::*;
use prolog::lib::control::*;
use prolog::lib::lists::*;
use prolog::machine::*; use prolog::machine::*;
#[cfg(test)] #[cfg(test)]
mod tests; mod tests;
pub static LISTS: &str = include_str!("./prolog/lib/lists.pl");
pub static CONTROL: &str = include_str!("./prolog/lib/control.pl");
fn process_buffer(wam: &mut Machine, buffer: &str) fn process_buffer(wam: &mut Machine, buffer: &str)
{ {
match parse_code(wam, buffer) { match parse_code(wam, buffer) {

View File

@@ -890,7 +890,7 @@ pub enum BuiltInInstruction {
GetCutPoint(RegType), GetCutPoint(RegType),
InferenceLevel, InferenceLevel,
InstallCleaner, InstallCleaner,
InstallInferenceCounter(RegType), InstallInferenceCounter(RegType, RegType, RegType),
InstallNewBlock, InstallNewBlock,
InternalCallN, InternalCallN,
IsAtomic(RegType), IsAtomic(RegType),
@@ -901,7 +901,8 @@ pub enum BuiltInInstruction {
IsRational(RegType), IsRational(RegType),
IsString(RegType), IsString(RegType),
IsVar(RegType), IsVar(RegType),
RemoveInferenceCounter(RegType), RemoveCallPolicyCheck,
RemoveInferenceCounter(RegType, RegType),
ResetBlock, ResetBlock,
RestoreCutPolicy, RestoreCutPolicy,
SetBall, SetBall,

View File

@@ -548,74 +548,89 @@ fn get_builtins(atom_tbl: TabledData<Atom>) -> Code {
compare_term_execute!(term_cmp_lt!()), // (@<)/2, 390. compare_term_execute!(term_cmp_lt!()), // (@<)/2, 390.
compare_term_execute!(term_cmp_eq!()), // (=@=)/2, 391. compare_term_execute!(term_cmp_eq!()), // (=@=)/2, 391.
compare_term_execute!(term_cmp_ne!()), // (\=@=)/2, 392. compare_term_execute!(term_cmp_ne!()), // (\=@=)/2, 392.
allocate!(4), // call_with_inference_limit/3, 393. allocate!(5), // call_with_inference_limit/3, 393.
fact![get_var_in_fact!(perm_v!(3), 1), fact![get_var_in_fact!(perm_v!(4), 1),
get_var_in_fact!(perm_v!(2), 2), get_var_in_fact!(perm_v!(3), 2),
get_var_in_fact!(perm_v!(1), 3)], get_var_in_fact!(perm_v!(2), 3)],
query![put_var!(perm_v!(4), 1)], query![put_var!(perm_v!(5), 1)],
get_current_block!(), get_current_block!(),
query![put_value!(perm_v!(3), 1), get_cp!(perm_v!(1)),
put_value!(perm_v!(2), 2), query![put_value!(perm_v!(4), 1),
put_value!(perm_v!(1), 3), put_value!(perm_v!(3), 2),
put_value!(perm_v!(4), 4)], put_value!(perm_v!(2), 3),
put_value!(perm_v!(5), 4),
put_value!(perm_v!(1), 5)],
goto_call!(404, 5), // goto call_with_inference_limit/4, 404.
query![put_value!(perm_v!(1), 1)],
deallocate!(), deallocate!(),
goto_execute!(400, 4), // goto call_with_inference_limit/4, 400. remove_call_policy_check!(),
try_me_else!(16), // call_with_inference_limit/4, 400. proceed!(),
allocate!(7), try_me_else!(18), // call_with_inference_limit/5, 404.
fact![get_var_in_fact!(perm_v!(6), 1), allocate!(9),
get_var_in_fact!(perm_v!(7), 2), fact![get_var_in_fact!(perm_v!(9), 1),
get_var_in_fact!(perm_v!(4), 3), get_var_in_fact!(perm_v!(6), 2),
get_var_in_fact!(perm_v!(3), 4)], get_var_in_fact!(perm_v!(5), 3),
get_var_in_fact!(perm_v!(3), 4),
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!(7)), install_inference_counter!(perm_v!(4), perm_v!(6), perm_v!(8)),
get_cp!(perm_v!(5)), query![put_value!(perm_v!(9), 1)],
query![put_value!(perm_v!(6), 1)],
call_n!(1), call_n!(1),
query![put_var!(perm_v!(2), 3)], remove_inference_counter!(perm_v!(4), perm_v!(7)),
remove_inference_counter!(perm_v!(2)), sub!(ArithmeticTerm::Reg(perm_v!(7)),
query![put_value!(perm_v!(4), 1), ArithmeticTerm::Reg(perm_v!(8)),
put_value!(perm_v!(5), 2)], 1),
sub!(ArithmeticTerm::Reg(perm_v!(6)),
ArithmeticTerm::Interm(1),
1),
query![put_value!(perm_v!(2), 1)],
is_call!(temp_v!(1), ArithmeticTerm::Interm(1)),
query![put_value!(perm_v!(5), 1),
put_value!(perm_v!(4), 2)],
inference_level!(), inference_level!(),
query![put_value!(perm_v!(3), 1), query![put_value!(perm_v!(4), 1),
put_value!(perm_v!(1), 2), put_value!(perm_v!(3), 2),
put_value!(perm_v!(2), 3)], put_value!(perm_v!(1), 3),
put_value!(perm_v!(2), 4)],
deallocate!(), deallocate!(),
goto_execute!(436, 3), // goto end_block/3, 436. goto_execute!(442, 4), // goto end_block/4, 442.
default_trust_me!(), // 416. default_trust_me!(), // 422.
allocate!(2), 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)],
query![put_value!(temp_v!(4), 1)], query![put_value!(temp_v!(4), 1)],
reset_block!(), reset_block!(),
query![put_var!(temp_v!(2), 1)], query![put_var!(temp_v!(3), 2)],
remove_inference_counter!(temp_v!(1)), remove_inference_counter!(perm_v!(3), temp_v!(2)),
query![put_var!(perm_v!(2), 1)], query![put_var!(perm_v!(2), 1)],
get_ball!(), get_ball!(),
erase_ball!(), erase_ball!(),
query![put_unsafe_value!(2, 1), query![put_value!(perm_v!(3), 1),
put_value!(perm_v!(1), 2)], put_unsafe_value!(2, 2),
put_value!(perm_v!(1), 3)],
deallocate!(), deallocate!(),
goto_execute!(429, 2), // goto handle_ile/2, 429. goto_execute!(435, 3), // goto handle_ile/3, 435.
try_me_else!(5), // handle_ile/2, 429. try_me_else!(4), // handle_ile/3, 435.
switch_on_term!(1, 1, 0, 0), fact![get_structure!(atom_tbl, "inference_limit_exceeded", 1, temp_v!(2), None),
fact![get_constant!(atom!("inference_limit_exceeded", atom_tbl), temp_v!(1)), unify_value!(temp_v!(1)),
get_constant!(atom!("inference_limit_exceeded", atom_tbl), temp_v!(2))], get_constant!(atom!("inference_limit_exceeded", atom_tbl), temp_v!(3))],
neck_cut!(), neck_cut!(),
proceed!(), proceed!(),
default_trust_me!(), default_trust_me!(),
goto_execute!(59, 1), // goto throw/1, 59.
try_me_else!(9), // end_block/3, 436.
allocate!(1),
fact![get_var_in_fact!(perm_v!(1), 1)],
query![put_value!(temp_v!(2), 1)], query![put_value!(temp_v!(2), 1)],
goto_execute!(59, 1), // goto throw/1, 59.
try_me_else!(6), // end_block/4, 442.
query![put_value!(temp_v!(3), 1)],
clean_up_block!(), clean_up_block!(),
query![put_value!(perm_v!(1), 1)], query![put_value!(temp_v!(2), 1)],
deallocate!(),
reset_block!(), reset_block!(),
proceed!(), proceed!(),
default_trust_me!(), default_trust_me!(),
install_inference_counter!(temp_v!(3)), query![put_value!(temp_v!(4), 2),
query![put_value!(temp_v!(2), 1)], put_var!(temp_v!(4), 4)],
install_inference_counter!(temp_v!(1), temp_v!(2), temp_v!(4)),
query![put_value!(temp_v!(3), 1)],
reset_block!(), reset_block!(),
fail!() fail!()
] ]

View File

@@ -209,8 +209,8 @@ impl fmt::Display for BuiltInInstruction {
write!(f, "clean_up_block"), write!(f, "clean_up_block"),
&BuiltInInstruction::DefaultTrustMe => &BuiltInInstruction::DefaultTrustMe =>
write!(f, "default_trust_me"), write!(f, "default_trust_me"),
&BuiltInInstruction::InstallInferenceCounter(r) => &BuiltInInstruction::InstallInferenceCounter(r1, r2, r3) =>
write!(f, "install_inference_counter {}", r), write!(f, "install_inference_counter {}, {}, {}", r1, r2, r3),
&BuiltInInstruction::EraseBall => &BuiltInInstruction::EraseBall =>
write!(f, "erase_ball"), write!(f, "erase_ball"),
&BuiltInInstruction::Fail => &BuiltInInstruction::Fail =>
@@ -267,8 +267,10 @@ impl fmt::Display for BuiltInInstruction {
write!(f, "number_test {}, {}, {} ", cmp, at_1, at_2), write!(f, "number_test {}, {}, {} ", cmp, at_1, at_2),
&BuiltInInstruction::DynamicCompareNumber(cmp) => &BuiltInInstruction::DynamicCompareNumber(cmp) =>
write!(f, "dynamic_number_test {}", cmp), write!(f, "dynamic_number_test {}", cmp),
&BuiltInInstruction::RemoveInferenceCounter(r) => &BuiltInInstruction::RemoveCallPolicyCheck =>
write!(f, "remove_inference_counter {}", r) write!(f, "remove_call_policy_check"),
&BuiltInInstruction::RemoveInferenceCounter(r1, r2) =>
write!(f, "remove_inference_counter {}, {}", r1, r2)
} }
} }
} }

13
src/prolog/lib/control.pl Normal file
View File

@@ -0,0 +1,13 @@
:- op(700, xfx, \=).
once(G) :- G, !.
\=(X, X) :- !, false.
\=(_, _).
between(Lower, Upper, Lower) :-
Lower =< Upper.
between(Lower1, Upper, X) :-
Lower1 < Upper,
Lower2 is Lower1 + 1,
between(Lower2, Upper, X).

View File

@@ -1,13 +0,0 @@
pub static CONTROL: &str = ":- op(700, xfx, \\=).
once(G) :- G, !.
\\=(X, X) :- !, false.
\\=(_, _).
between(Lower, Upper, Lower) :-
Lower =< Upper.
between(Lower1, Upper, X) :-
Lower1 < Upper,
Lower2 is Lower1 + 1,
between(Lower2, Upper, X).";

57
src/prolog/lib/lists.pl Normal file
View File

@@ -0,0 +1,57 @@
member(X, [X|_]).
member(X, [_|Xs]) :- member(X, Xs).
select(X, [X|Xs], Xs).
select(X, [Y|Xs], [Y|Ys]) :- select(X, Xs, Ys).
append([], R, R).
append([X|L], R, [X|S]) :- append(L, R, S).
memberchk(X, Xs) :- member(X, Xs), !.
reverse(Xs, Ys) :- var(Ys), !, reverse(Xs, [], Ys).
reverse(Ys, Xs) :- reverse(Xs, [], Ys).
reverse([], Ys, Ys).
reverse([H|T], Ps, Rs) :-
reverse(T, [H|Ps], Rs).
maplist(_, []).
maplist(Cont1, [E1|E1s]) :-
call(Cont1, E1),
maplist(Cont1, E1s).
maplist(_, [], []).
maplist(Cont2, [E1|E1s], [E2|E2s]) :-
call(Cont2, E1, E2),
maplist(Cont2, E1s, E2s).
maplist(_, [], [], []).
maplist(Cont3, [E1|E1s], [E2|E2s], [E3|E3s]) :-
call(Cont3, E1, E2, E3),
maplist(Cont3, E1s, E2s, E3s).
maplist(_, [], [], [], []).
maplist(Cont, [E1|E1s], [E2|E2s], [E3|E3s], [E4|E4s]) :-
call(Cont, E1, E2, E3, E4),
maplist(Cont, E1s, E2s, E3s, E4s).
maplist(_, [], [], [], [], []).
maplist(Cont, [E1|E1s], [E2|E2s], [E3|E3s], [E4|E4s], [E5|E5s]) :-
call(Cont, E1, E2, E3, E4, E5),
maplist(Cont, E1s, E2s, E3s, E4s, E5s).
maplist(_, [], [], [], [], [], []).
maplist(Cont, [E1|E1s], [E2|E2s], [E3|E3s], [E4|E4s], [E5|E5s], [E6|E6s]) :-
call(Cont, E1, E2, E3, E4, E5, E6),
maplist(Cont, E1s, E2s, E3s, E4s, E5s, E6s).
maplist(_, [], [], [], [], [], [], []).
maplist(Cont, [E1|E1s], [E2|E2s], [E3|E3s], [E4|E4s], [E5|E5s], [E6|E6s], [E7|E7s]) :-
call(Cont, E1, E2, E3, E4, E5, E6, E7),
maplist(Cont, E1s, E2s, E3s, E4s, E5s, E6s, E7s).
maplist(_, [], [], [], [], [], [], [], []).
maplist(Cont, [E1|E1s], [E2|E2s], [E3|E3s], [E4|E4s], [E5|E5s], [E6|E6s], [E7|E7s], [E8|E8s]) :-
call(Cont, E1, E2, E3, E4, E5, E6, E7),
maplist(Cont, E1s, E2s, E3s, E4s, E5s, E6s, E7s, E8s).

View File

@@ -1,57 +0,0 @@
pub static LISTS: &str = "member(X, [X|_]).
member(X, [_|Xs]) :- member(X, Xs).
select(X, [X|Xs], Xs).
select(X, [Y|Xs], [Y|Ys]) :- select(X, Xs, Ys).
append([], R, R).
append([X|L], R, [X|S]) :- append(L, R, S).
memberchk(X, Xs) :- member(X, Xs), !.
reverse(Xs, Ys) :- var(Ys), !, reverse(Xs, [], Ys).
reverse(Ys, Xs) :- reverse(Xs, [], Ys).
reverse([], Ys, Ys).
reverse([H|T], Ps, Rs) :-
reverse(T, [H|Ps], Rs).
maplist(_, []).
maplist(Cont1, [E1|E1s]) :-
call(Cont1, E1),
maplist(Cont1, E1s).
maplist(_, [], []).
maplist(Cont2, [E1|E1s], [E2|E2s]) :-
call(Cont2, E1, E2),
maplist(Cont2, E1s, E2s).
maplist(_, [], [], []).
maplist(Cont3, [E1|E1s], [E2|E2s], [E3|E3s]) :-
call(Cont3, E1, E2, E3),
maplist(Cont3, E1s, E2s, E3s).
maplist(_, [], [], [], []).
maplist(Cont, [E1|E1s], [E2|E2s], [E3|E3s], [E4|E4s]) :-
call(Cont, E1, E2, E3, E4),
maplist(Cont, E1s, E2s, E3s, E4s).
maplist(_, [], [], [], [], []).
maplist(Cont, [E1|E1s], [E2|E2s], [E3|E3s], [E4|E4s], [E5|E5s]) :-
call(Cont, E1, E2, E3, E4, E5),
maplist(Cont, E1s, E2s, E3s, E4s, E5s).
maplist(_, [], [], [], [], [], []).
maplist(Cont, [E1|E1s], [E2|E2s], [E3|E3s], [E4|E4s], [E5|E5s], [E6|E6s]) :-
call(Cont, E1, E2, E3, E4, E5, E6),
maplist(Cont, E1s, E2s, E3s, E4s, E5s, E6s).
maplist(_, [], [], [], [], [], [], []).
maplist(Cont, [E1|E1s], [E2|E2s], [E3|E3s], [E4|E4s], [E5|E5s], [E6|E6s], [E7|E7s]) :-
call(Cont, E1, E2, E3, E4, E5, E6, E7),
maplist(Cont, E1s, E2s, E3s, E4s, E5s, E6s, E7s).
maplist(_, [], [], [], [], [], [], [], []).
maplist(Cont, [E1|E1s], [E2|E2s], [E3|E3s], [E4|E4s], [E5|E5s], [E6|E6s], [E7|E7s], [E8|E8s]) :-
call(Cont, E1, E2, E3, E4, E5, E6, E7),
maplist(Cont, E1s, E2s, E3s, E4s, E5s, E6s, E7s, E8s).";

View File

@@ -1,3 +0,0 @@
pub mod control;
pub mod lists;

View File

@@ -2,14 +2,12 @@ use prolog::and_stack::*;
use prolog::builtins::CodeDir; use prolog::builtins::CodeDir;
use prolog::ast::*; use prolog::ast::*;
use prolog::copier::*; use prolog::copier::*;
use prolog::num::{BigInt, BigUint, Zero, One}; use prolog::num::{BigInt, Zero, One};
use prolog::or_stack::*; use prolog::or_stack::*;
use prolog::tabled_rc::*; use prolog::tabled_rc::*;
use downcast::Any; use downcast::Any;
use std::cmp::Ordering;
use std::collections::binary_heap::BinaryHeap;
use std::mem::swap; use std::mem::swap;
use std::ops::{Index, IndexMut}; use std::ops::{Index, IndexMut};
use std::rc::Rc; use std::rc::Rc;
@@ -353,27 +351,11 @@ pub(crate) struct DefaultCallPolicy {}
impl CallPolicy for DefaultCallPolicy {} impl CallPolicy for DefaultCallPolicy {}
#[derive(Clone, Eq, PartialEq)]
struct InferenceLimit(BigUint);
// ensure the heap behaves as a min-heap.
impl Ord for InferenceLimit {
fn cmp(&self, other: &InferenceLimit) -> Ordering {
other.0.cmp(&self.0)
}
}
impl PartialOrd for InferenceLimit {
fn partial_cmp(&self, other: &InferenceLimit) -> Option<Ordering> {
Some(self.cmp(other))
}
}
pub(crate) struct CallWithInferenceLimitCallPolicy { pub(crate) struct CallWithInferenceLimitCallPolicy {
atom_tbl: TabledData<Atom>, atom_tbl: TabledData<Atom>,
pub(crate) prev_policy: Box<CallPolicy>, pub(crate) prev_policy: Box<CallPolicy>,
count: BigUint, count: BigInt,
limits: BinaryHeap<InferenceLimit> limits: Vec<(Rc<BigInt>, usize)>
} }
impl CallWithInferenceLimitCallPolicy { impl CallWithInferenceLimitCallPolicy {
@@ -383,33 +365,47 @@ impl CallWithInferenceLimitCallPolicy {
swap(&mut prev_policy, policy); swap(&mut prev_policy, policy);
let new_policy = CallWithInferenceLimitCallPolicy { atom_tbl, prev_policy, let new_policy = CallWithInferenceLimitCallPolicy { atom_tbl, prev_policy,
count: BigUint::zero(), count: BigInt::zero(),
limits: BinaryHeap::new() }; limits: vec![] };
*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) = self.limits.peek() { if let Some(&(ref limit, bp)) = self.limits.last() {
if self.count == limit.0 { if self.count == **limit {
return Err(vec![heap_atom!("inference_limit_exceeded", self.atom_tbl)]) return Err(functor!(self.atom_tbl,
"inference_limit_exceeded",
1,
[HeapCellValue::Addr(Addr::Con(Constant::Usize(bp)))]));
} else { } else {
self.count = BigUint::one() + &self.count; self.count = BigInt::one() + &self.count;
} }
} }
Ok(()) Ok(())
} }
pub(crate) fn add_limit(&mut self, limit: Rc<BigInt>) { // returns the count.
match limit.to_biguint() { pub(crate) fn add_limit(&mut self, limit: Rc<BigInt>, b: usize) -> Rc<BigInt> {
Some(limit) => self.limits.push(InferenceLimit(limit + &self.count)), let limit = Rc::new(&*limit + &self.count);
_ => panic!("add_limit: expected unsigned integer.")
match self.limits.last().cloned() {
Some((ref inner_limit, _)) if *inner_limit <= limit => {},
_ => self.limits.push((limit, b))
}; };
Rc::new(self.count.clone())
} }
pub(crate) fn remove_limit(&mut self) -> Option<BigUint> { // returns the count.
self.limits.pop().map(|i| i.0 - &self.count) pub(crate) fn remove_limit(&mut self, b: usize) -> Rc<BigInt> {
if let Some((_, bp)) = self.limits.last().cloned() {
if bp == b {
self.limits.pop();
}
}
Rc::new(self.count.clone())
} }
pub(crate) fn is_empty(&self) -> bool { pub(crate) fn is_empty(&self) -> bool {

View File

@@ -1315,7 +1315,7 @@ impl MachineState {
match a2 { match a2 {
Addr::Con(Constant::Usize(bp)) => Addr::Con(Constant::Usize(bp)) =>
if self.b <= bp { if self.b <= bp + 1 {
let a2 = Addr::Con(atom!("!", self.atom_tbl)); let a2 = Addr::Con(atom!("!", self.atom_tbl));
self.unify(a1, a2); self.unify(a1, a2);
} else { } else {
@@ -1340,24 +1340,30 @@ impl MachineState {
{ {
Some(cut_policy) => cut_policy.push_cont_pt(addr, b, block), Some(cut_policy) => cut_policy.push_cont_pt(addr, b, block),
None => panic!("install_cleaner: should have installed \\ None => panic!("install_cleaner: should have installed \\
SetupCallCleanupCutPolicy.") SetupCallCleanupCutPolicy.")
}; };
self.p += 1; self.p += 1;
}, },
&BuiltInInstruction::InstallInferenceCounter(r) => { &BuiltInInstruction::InstallInferenceCounter(r1, r2, r3) => { // A1 = B, A2 = L
let addr = self.store(self.deref(self[r].clone())); let a1 = self.store(self.deref(self[r1].clone()));
let a2 = self.store(self.deref(self[r2].clone()));
if call_policy.downcast_ref::<CallWithInferenceLimitCallPolicy>().is_err() { if call_policy.downcast_ref::<CallWithInferenceLimitCallPolicy>().is_err() {
CallWithInferenceLimitCallPolicy::new_in_place(self.atom_tbl.clone(), call_policy); CallWithInferenceLimitCallPolicy::new_in_place(self.atom_tbl.clone(),
call_policy);
} }
self.p += 1; self.p += 1;
match addr { match (a1, a2) {
Addr::Con(Constant::Number(Number::Integer(n))) => (Addr::Con(Constant::Usize(bp)),
Addr::Con(Constant::Number(Number::Integer(n)))) =>
match call_policy.downcast_mut::<CallWithInferenceLimitCallPolicy>().ok() { match call_policy.downcast_mut::<CallWithInferenceLimitCallPolicy>().ok() {
Some(call_policy) => call_policy.add_limit(n), Some(call_policy) => {
let count = call_policy.add_limit(n, bp);
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.")
}, },
@@ -1434,22 +1440,21 @@ SetupCallCleanupCutPolicy.")
_ => self.fail = true _ => self.fail = true
}; };
}, },
&BuiltInInstruction::RemoveInferenceCounter(r) => { &BuiltInInstruction::RemoveCallPolicyCheck => {
let restore_default = let restore_default =
match call_policy.downcast_mut::<CallWithInferenceLimitCallPolicy>().ok() { match call_policy.downcast_mut::<CallWithInferenceLimitCallPolicy>().ok() {
Some(call_policy) => { Some(call_policy) => {
if let Some(diff) = call_policy.remove_limit() { let a1 = self.store(self.deref(self[temp_v!(1)].clone()));
let addr = self[r].clone();
self.unify(addr, Addr::Con(integer!(diff)));
} else {
panic!("remove_inference_counters: no limit found.");
}
if call_policy.is_empty() { if let Addr::Con(Constant::Usize(bp)) = a1 {
if call_policy.is_empty() && bp == self.b {
Some(call_policy.into_inner()) Some(call_policy.into_inner())
} else { } else {
None None
} }
} else {
panic!("remove_inference_counter: expected Usize in A1.");
}
}, },
None => panic!("remove_inference_counters: requires \\ None => panic!("remove_inference_counters: requires \\
CallWithInferenceLimitCallPolicy.") CallWithInferenceLimitCallPolicy.")
@@ -1461,6 +1466,25 @@ SetupCallCleanupCutPolicy.")
self.p += 1; self.p += 1;
}, },
&BuiltInInstruction::RemoveInferenceCounter(r1, r2) => { // A1 = B, A2 = Count.
match call_policy.downcast_mut::<CallWithInferenceLimitCallPolicy>().ok() {
Some(call_policy) => {
let a1 = self.store(self.deref(self[r1].clone()));
if let Addr::Con(Constant::Usize(bp)) = a1 {
let count = call_policy.remove_limit(bp);
self[r2] = Addr::Con(Constant::Number(Number::Integer(count)));
} else {
panic!("remove_inference_counter: expected Usize in A1.");
}
},
None => panic!("remove_inference_counters: requires \\
CallWithInferenceLimitCallPolicy.")
};
self.p += 1;
},
&BuiltInInstruction::RestoreCutPolicy => { &BuiltInInstruction::RestoreCutPolicy => {
let restore_default = let restore_default =
if let Ok(cut_policy) = cut_policy.downcast_ref::<SetupCallCleanupCutPolicy>() { if let Ok(cut_policy) = cut_policy.downcast_ref::<SetupCallCleanupCutPolicy>() {

View File

@@ -431,6 +431,12 @@ macro_rules! add {
) )
} }
macro_rules! sub {
($at_1:expr, $at_2:expr, $o:expr) => (
Line::Arithmetic(ArithmeticInstruction::Sub($at_1, $at_2, $o))
)
}
macro_rules! get_arg_call { macro_rules! get_arg_call {
() => ( () => (
Line::BuiltIn(BuiltInInstruction::GetArgCall) Line::BuiltIn(BuiltInInstruction::GetArgCall)
@@ -624,14 +630,14 @@ macro_rules! term_cmp_eq {
} }
macro_rules! install_inference_counter { macro_rules! install_inference_counter {
($r:expr) => ( ($r1:expr, $r2:expr, $r3:expr) => (
Line::BuiltIn(BuiltInInstruction::InstallInferenceCounter($r)) Line::BuiltIn(BuiltInInstruction::InstallInferenceCounter($r1, $r2, $r3))
) )
} }
macro_rules! remove_inference_counter { macro_rules! remove_inference_counter {
($r:expr) => ( ($r1:expr, $r2:expr) => (
Line::BuiltIn(BuiltInInstruction::RemoveInferenceCounter($r)) Line::BuiltIn(BuiltInInstruction::RemoveInferenceCounter($r1, $r2))
) )
} }
@@ -646,3 +652,9 @@ macro_rules! default_trust_me {
Line::BuiltIn(BuiltInInstruction::DefaultTrustMe) Line::BuiltIn(BuiltInInstruction::DefaultTrustMe)
) )
} }
macro_rules! remove_call_policy_check {
() => (
Line::BuiltIn(BuiltInInstruction::RemoveCallPolicyCheck)
)
}

View File

@@ -18,7 +18,6 @@ pub mod heap_print;
pub mod indexing; pub mod indexing;
pub mod io; pub mod io;
pub mod iterators; pub mod iterators;
pub mod lib;
pub mod machine; pub mod machine;
pub mod or_stack; pub mod or_stack;
pub mod parser; pub mod parser;