[[package]]
name = "num-traits"
-version = "0.2.16"
+version = "0.2.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f30b0abd723be7e2ffca1272140fac1a2f084c77ec3e123c192b66af1ee9e6c2"
+checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c"
dependencies = [
"autocfg",
]
InstallSCCCleaner,
#[strum_discriminants(strum(props(Arity = "3", Name = "$install_inference_counter")))]
InstallInferenceCounter,
+ #[strum_discriminants(strum(props(Arity = "1", Name = "$inference_count")))]
+ InferenceCount,
#[strum_discriminants(strum(props(Arity = "1", Name = "$lh_length")))]
LiftedHeapLength,
#[strum_discriminants(strum(props(Arity = "3", Name = "$load_library_as_stream")))]
&Instruction::CallHeadIsDynamic |
&Instruction::CallInstallSCCCleaner |
&Instruction::CallInstallInferenceCounter |
+ &Instruction::CallInferenceCount |
&Instruction::CallLiftedHeapLength |
&Instruction::CallLoadLibraryAsStream |
&Instruction::CallModuleExists |
&Instruction::ExecuteHeadIsDynamic |
&Instruction::ExecuteInstallSCCCleaner |
&Instruction::ExecuteInstallInferenceCounter |
+ &Instruction::ExecuteInferenceCount |
&Instruction::ExecuteLiftedHeapLength |
&Instruction::ExecuteLoadLibraryAsStream |
&Instruction::ExecuteModuleExists |
macro_rules! increment_call_count {
($s:expr) => {{
- if !($s.increment_call_count_fn)(&mut $s) {
+ if !$s.increment_call_count() {
$s.backtrack();
continue;
}
try_or_throw!(self.machine_st, self.install_inference_counter());
step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
}
+ &Instruction::CallInferenceCount => {
+ let global_count = self.machine_st.cwil.global_count.clone();
+ self.inference_count(self.machine_st.registers[1], global_count);
+ step_or_fail!(self, self.machine_st.p += 1);
+ }
+ &Instruction::ExecuteInferenceCount => {
+ let global_count = self.machine_st.cwil.global_count.clone();
+ self.inference_count(self.machine_st.registers[1], global_count);
+ step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
+ }
&Instruction::CallLiftedHeapLength => {
self.lifted_heap_length();
step_or_fail!(self, self.machine_st.p += 1);
pub(crate) unify_fn: fn(&mut MachineState),
pub(crate) bind_fn: fn(&mut MachineState, Ref, HeapCellValue),
pub(crate) run_cleaners_fn: fn(&mut Machine) -> bool,
- pub(crate) increment_call_count_fn: fn(&mut MachineState) -> bool,
}
impl fmt::Debug for MachineState {
return true;
}
+ self.cwil.global_count += 1;
+
if let Some(&(ref limit, block)) = self.cwil.limits.last() {
- if self.cwil.count == *limit {
+ if self.cwil.local_count == *limit {
self.cwil.inference_limit_exceeded = true;
self.block = block;
self.unwind_stack();
return false;
} else {
- self.cwil.count += 1;
+ self.cwil.local_count += 1;
}
}
#[allow(clippy::upper_case_acronyms)]
#[derive(Debug)]
pub(crate) struct CWIL {
- count: Integer,
+ local_count: Integer,
+ pub(crate) global_count: Integer,
limits: Vec<(Integer, usize)>,
pub(crate) inference_limit_exceeded: bool,
}
impl CWIL {
pub(crate) fn new() -> Self {
CWIL {
- count: Integer::from(0),
+ local_count: Integer::from(0),
+ global_count: Integer::from(0),
limits: vec![],
inference_limit_exceeded: false,
}
}
- pub(crate) fn add_limit(&mut self, limit: usize, block: usize) -> &Integer {
- let mut limit = Integer::from(limit);
- limit += &self.count;
+ pub(crate) fn add_limit(&mut self, mut limit: Integer, block: usize) -> &Integer {
+ limit += &self.local_count;
match self.limits.last() {
Some((ref inner_limit, _)) if *inner_limit <= limit => {}
_ => self.limits.push((limit, block)),
- };
+ }
- &self.count
+ &self.local_count
}
#[inline(always)]
}
}
- &self.count
+ &self.local_count
}
#[inline(always)]
pub(crate) fn reset(&mut self) {
- self.count = Integer::from(0);
+ self.local_count = Integer::from(0);
self.limits.clear();
self.inference_limit_exceeded = false;
}
unify_fn: MachineState::unify,
bind_fn: MachineState::bind,
run_cleaners_fn: |_| false,
- increment_call_count_fn: |_| true,
}
}
use crate::parser::ast::*;
use crate::parser::parser::*;
-use dashu::integer::Sign;
-use dashu::integer::UBig;
+use dashu::integer::{Sign, UBig};
use lazy_static::lazy_static;
use num_order::NumOrd;
let a2 = self.deref_register(2);
let n = match Number::try_from(a2) {
- Ok(Number::Fixnum(bp)) => bp.get_num() as usize,
- Ok(Number::Integer(n)) => {
- let value: usize = (&*n).try_into().unwrap();
- value
- }
+ Ok(Number::Fixnum(bp)) => Integer::from(bp.get_num() as usize),
+ Ok(Number::Integer(n)) => (*n).clone(),
_ => {
let stub = functor_stub(atom!("call_with_inference_limit"), 3);
let bp = cell_as_fixnum!(a1).get_num() as usize;
let a3 = self.deref_register(3);
- let count = self.machine_st.cwil.add_limit(n, bp);
- let result = count.try_into();
- if let Ok(value) = result {
- self.machine_st.unify_fixnum(Fixnum::build_with(value), a3);
- } else {
- let count = arena_alloc!(count.clone(), &mut self.machine_st.arena);
- self.machine_st.unify_big_int(count, a3);
- }
-
- self.machine_st.increment_call_count_fn = MachineState::increment_call_count;
+ let count = self.machine_st.cwil.add_limit(n, bp).clone();
+ self.inference_count(a3, count);
Ok(())
}
+ #[inline(always)]
+ pub(crate) fn inference_count(&mut self, count_var: HeapCellValue, count: Integer) {
+ if let Some(value) = <&Integer as TryInto<i64>>::try_into(&count).ok() {
+ self.machine_st
+ .unify_fixnum(Fixnum::build_with(value), count_var);
+ } else {
+ let count = arena_alloc!(count, &mut self.machine_st.arena);
+ self.machine_st.unify_big_int(count, count_var);
+ }
+ }
+
#[inline(always)]
pub(crate) fn module_exists(&mut self) {
let module = self.deref_register(1);
if bp == self.machine_st.b && self.machine_st.cwil.is_empty() {
self.machine_st.cwil.reset();
- self.machine_st.increment_call_count_fn = |_| true;
}
}