Merge branch 'master' into library-use-case

This commit is contained in:
Nicolas Luck
2023-12-04 20:06:14 +01:00
47 changed files with 1622 additions and 821 deletions

View File

@@ -348,7 +348,7 @@ pub(crate) fn int_pow(n1: Number, n2: Number, arena: &mut Arena) -> Result<Numbe
(Number::Fixnum(n1), Number::Integer(n2)) => {
let n1_i = n1.get_num();
if !(n1_i == 1 || n1_i == 0 || n1_i == -1) && n2.is_zero() {
if !(n1_i == 1 || n1_i == 0 || n1_i == -1) && n2.is_negative() {
let n = Number::Fixnum(n1);
Err(numerical_type_error(ValidType::Float, n, stub_gen))
} else {
@@ -359,7 +359,7 @@ pub(crate) fn int_pow(n1: Number, n2: Number, arena: &mut Arena) -> Result<Numbe
(Number::Integer(n1), Number::Fixnum(n2)) => {
let n2_i = n2.get_num();
if !(*n1 == Integer::from(1) || n1.is_zero() || *n1 == Integer::from(-1)) && n2_i < 0 {
if !(n1.is_one() || n1.is_zero() || n1.num_eq(&-1)) && n2_i < 0 {
let n = Number::Integer(n1);
Err(numerical_type_error(ValidType::Float, n, stub_gen))
} else {
@@ -368,9 +368,7 @@ pub(crate) fn int_pow(n1: Number, n2: Number, arena: &mut Arena) -> Result<Numbe
}
}
(Number::Integer(n1), Number::Integer(n2)) => {
if !(*n1 == Integer::from(1) || n1.is_zero() || *n1 == Integer::from(-1))
&& n2.is_zero()
{
if !(n1.is_one() || n1.is_zero() || n1.num_eq(&-1)) && n2.is_negative() {
let n = Number::Integer(n1);
Err(numerical_type_error(ValidType::Float, n, stub_gen))
} else {
@@ -711,11 +709,8 @@ pub(crate) fn shl(n1: Number, n2: Number, arena: &mut Arena) -> Result<Number, M
(Number::Fixnum(n1), Number::Integer(n2)) => {
let n1 = Integer::from(n1.get_num());
match (&*n2).try_into() as Result<u32, _> {
Ok(n2) => {
let n1: u64 = n1.try_into().unwrap();
Ok(Number::arena_from(n1 << n2, arena))
}
match (&*n2).try_into() as Result<usize, _> {
Ok(n2) => Ok(Number::arena_from(n1 << n2, arena)),
_ => Ok(Number::arena_from(n1 << usize::max_value(), arena)),
}
}
@@ -726,11 +721,8 @@ pub(crate) fn shl(n1: Number, n2: Number, arena: &mut Arena) -> Result<Number, M
arena,
)),
},
(Number::Integer(n1), Number::Integer(n2)) => match (&*n2).try_into() as Result<u32, _> {
Ok(n2) => {
let n1: u64 = (&*n1).try_into().unwrap();
Ok(Number::arena_from(Integer::from(n1 << n2), arena))
}
(Number::Integer(n1), Number::Integer(n2)) => match (&*n2).try_into() as Result<usize, _> {
Ok(n2) => Ok(Number::arena_from(Integer::from(&*n1 << n2), arena)),
_ => Ok(Number::arena_from(
Integer::from(&*n1 << usize::max_value()),
arena,

View File

@@ -18,6 +18,7 @@ pub trait CopierTarget: IndexMut<usize, Output = HeapCellValue> {
fn store(&self, value: HeapCellValue) -> HeapCellValue;
fn deref(&self, value: HeapCellValue) -> HeapCellValue;
fn push(&mut self, value: HeapCellValue);
fn push_attr_var_queue(&mut self, attr_var_loc: usize);
fn stack(&mut self) -> &mut Stack;
fn threshold(&self) -> usize;
}
@@ -73,7 +74,6 @@ impl<T: CopierTarget> CopyTermState<T> {
if h >= self.old_h {
*self.value_at_scan() = list_loc_as_cell!(h);
self.scan += 1;
return;
}
}
@@ -96,14 +96,19 @@ impl<T: CopierTarget> CopyTermState<T> {
.store(self.target.deref(heap_loc_as_cell!(addr + 1)));
if !cdr.is_var() {
// mark addr + 1 as a list back edge in the cdr of the list
self.trail_list_cell(addr + 1, threshold);
self.target[addr + 1].set_mark_bit(true);
self.target[addr + 1].set_forwarding_bit(true);
} else {
let car = self
.target
.store(self.target.deref(heap_loc_as_cell!(addr)));
if !car.is_var() {
// mark addr as a list back edge in the car of the list
self.trail_list_cell(addr, threshold);
self.target[addr].set_mark_bit(true);
}
}
@@ -178,6 +183,7 @@ impl<T: CopierTarget> CopyTermState<T> {
for (threshold, list_loc) in iter {
self.target[threshold] = list_loc_as_cell!(self.target.threshold());
self.target.push_attr_var_queue(threshold - 1);
self.copy_attr_var_list(list_loc);
}
}
@@ -263,6 +269,7 @@ impl<T: CopierTarget> CopyTermState<T> {
}
fn copy_var(&mut self, addr: HeapCellValue) {
let index = addr.get_value() as usize;
let rd = self.target.deref(addr);
let ra = self.target.store(rd);
@@ -271,7 +278,20 @@ impl<T: CopierTarget> CopyTermState<T> {
if h >= self.old_h {
*self.value_at_scan() = ra;
self.scan += 1;
return;
}
}
(HeapCellValueTag::Lis, h) => {
if h >= self.old_h && self.target[index].get_mark_bit() {
*self.value_at_scan() = heap_loc_as_cell!(
if ra.get_forwarding_bit() {
h + 1
} else {
h
}
);
self.scan += 1;
return;
}
}
@@ -356,12 +376,16 @@ impl<T: CopierTarget> CopyTermState<T> {
}
}
fn unwind_trail(&mut self) {
for (r, value) in self.trail.drain(0..) {
fn unwind_trail(mut self) {
for (r, value) in self.trail {
let index = r.get_value() as usize;
match r.get_tag() {
RefTag::AttrVar | RefTag::HeapCell => self.target[index] = value,
RefTag::AttrVar | RefTag::HeapCell => {
self.target[index] = value;
self.target[index].set_mark_bit(false);
self.target[index].set_forwarding_bit(false);
}
RefTag::StackCell => self.target.stack()[index] = value,
}
}

View File

@@ -663,12 +663,16 @@ impl VariableClassifier {
state_stack.last(),
Some(TraversalState::RemoveBranchNum)
) {
// check if the second-to-last element is a regular BuildDisjunct, as we don't
// want to add GetPrevLevel in case of a TrustMe.
matches!(
state_stack.iter().rev().nth(1),
Some(TraversalState::BuildDisjunct(..))
)
// check if the second-to-last element
// is a regular BuildDisjunct, as we
// don't want to add GetPrevLevel in
// case of a TrustMe.
match state_stack.iter().rev().nth(1) {
Some(&TraversalState::BuildDisjunct(preceding_len)) => {
preceding_len + 1 == build_stack.len()
}
_ => false,
}
} else {
false
};

View File

@@ -36,7 +36,7 @@ macro_rules! try_or_throw {
macro_rules! increment_call_count {
($s:expr) => {{
if !($s.increment_call_count_fn)(&mut $s) {
if !$s.increment_call_count() {
$s.backtrack();
continue;
}
@@ -208,6 +208,7 @@ impl MachineState {
l
}
(HeapCellValueTag::Fixnum |
HeapCellValueTag::CutPoint |
HeapCellValueTag::Char |
HeapCellValueTag::F64) => {
c
@@ -3675,6 +3676,16 @@ impl Machine {
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);
@@ -4128,6 +4139,14 @@ impl Machine {
try_or_throw!(self.machine_st, self.define_foreign_struct());
step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
}
&Instruction::CallJsEval => {
try_or_throw!(self.machine_st, self.js_eval());
step_or_fail!(self, self.machine_st.p += 1);
}
&Instruction::ExecuteJsEval => {
try_or_throw!(self.machine_st, self.js_eval());
step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
}
&Instruction::CallCurrentTime => {
self.current_time();
step_or_fail!(self, self.machine_st.p += 1);

View File

@@ -57,10 +57,11 @@ impl Machine {
or_frame.prelude.attr_var_queue_len = 0;
self.machine_st.b = stub_b;
self.machine_st.hb = self.machine_st.heap.len();
}
pub fn run_query(&mut self, query: String) -> QueryResult {
println!("Query: {}", query);
// println!("Query: {}", query);
// Parse the query so we can analyze and then call the term
let mut parser = Parser::new(
Stream::from_owned_string(query, &mut self.machine_st.arena),
@@ -87,6 +88,7 @@ impl Machine {
.expect("couldn't get code index")
.local()
.unwrap();
self.machine_st.b0 = self.machine_st.b;
let var_names: IndexMap<_, _> = term_write_result
.var_dict
@@ -192,7 +194,7 @@ impl Machine {
let outputter = printer.print();
let output: String = outputter.result();
println!("Result: {} = {}", var_key.to_string(), output);
// println!("Result: {} = {}", var_key.to_string(), output);
bindings.insert(var_key.to_string(), Value::try_from(output).expect("asdfs"));
}
@@ -444,10 +446,7 @@ mod tests {
}
// Check if the block is a query
if block.starts_with("query") {
// Extract the query from the block
let query = &block[5..];
if let Some(query) = block.strip_prefix("query") {
i += 1;
println!("query #{}: {}", i, query);
// Parse and execute the query
@@ -457,10 +456,7 @@ mod tests {
// Print the result
println!("{:?}", result);
} else if block.starts_with("consult") {
// Extract the code from the block
let code = &block[7..];
} else if let Some(code) = block.strip_prefix("consult") {
println!("load code: {}", code);
// Load the code into the machine

View File

@@ -148,9 +148,10 @@ impl<'a, LS: LoadState<'a>> Drop for Loader<'a, LS> {
}
}
#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq)]
#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq, Default)]
pub enum CompilationTarget {
Module(Atom),
#[default]
User,
}
@@ -163,13 +164,6 @@ impl fmt::Display for CompilationTarget {
}
}
impl Default for CompilationTarget {
#[inline]
fn default() -> Self {
CompilationTarget::User
}
}
impl CompilationTarget {
#[inline]
pub(crate) fn module_name(&self) -> Atom {

View File

@@ -492,13 +492,22 @@ impl MachineState {
self.permission_error(Permission::Modify, atom!("static_module"), module)
}
SessionError::ExistenceError(err) => self.existence_error(err),
SessionError::ModuleDoesNotContainExport(..) => {
let error_atom = atom!("module_does_not_contain_claimed_export");
SessionError::ModuleDoesNotContainExport(module_name, key) => {
let functor_stub = functor_stub(key.0, key.1);
let stub = functor!(
atom!("module_does_not_contain_claimed_export"),
[
atom(module_name),
str(self.heap.len() + 4, 0)
],
[functor_stub]
);
self.permission_error(
Permission::Access,
atom!("private_procedure"),
functor!(error_atom),
stub,
)
}
SessionError::ModuleCannotImportSelf(module_name) => {

View File

@@ -96,7 +96,6 @@ pub struct MachineState {
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 {
@@ -290,6 +289,11 @@ impl<'a> CopierTarget for CopyTerm<'a> {
self.state.heap.push(hcv);
}
#[inline(always)]
fn push_attr_var_queue(&mut self, attr_var_loc: usize) {
self.state.attr_var_init.attr_var_queue.push(attr_var_loc);
}
#[inline(always)]
fn store(&self, value: HeapCellValue) -> HeapCellValue {
self.state.store(value)
@@ -308,6 +312,7 @@ impl<'a> CopierTarget for CopyTerm<'a> {
#[derive(Debug)]
pub(super) struct CopyBallTerm<'a> {
attr_var_queue: &'a mut Vec<usize>,
stack: &'a mut Stack,
heap: &'a mut Heap,
heap_boundary: usize,
@@ -315,10 +320,16 @@ pub(super) struct CopyBallTerm<'a> {
}
impl<'a> CopyBallTerm<'a> {
pub(super) fn new(stack: &'a mut Stack, heap: &'a mut Heap, stub: &'a mut Heap) -> Self {
pub(super) fn new(
attr_var_queue: &'a mut Vec<usize>,
stack: &'a mut Stack,
heap: &'a mut Heap,
stub: &'a mut Heap,
) -> Self {
let hb = heap.len();
CopyBallTerm {
attr_var_queue,
stack,
heap,
heap_boundary: hb,
@@ -360,6 +371,11 @@ impl<'a> CopierTarget for CopyBallTerm<'a> {
self.stub.push(value);
}
#[inline(always)]
fn push_attr_var_queue(&mut self, attr_var_loc: usize) {
self.attr_var_queue.push(attr_var_loc);
}
fn store(&self, value: HeapCellValue) -> HeapCellValue {
read_heap_cell!(value,
(HeapCellValueTag::Var | HeapCellValueTag::AttrVar, h) => {
@@ -417,15 +433,17 @@ impl 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;
}
}
@@ -967,7 +985,8 @@ impl MachineState {
#[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,
}
@@ -975,22 +994,22 @@ pub(crate) struct CWIL {
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)]
@@ -1001,12 +1020,12 @@ impl CWIL {
}
}
&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;
}

View File

@@ -60,7 +60,6 @@ impl MachineState {
unify_fn: MachineState::unify,
bind_fn: MachineState::bind,
run_cleaners_fn: |_| false,
increment_call_count_fn: |_| true,
}
}
@@ -335,7 +334,12 @@ impl MachineState {
self.ball.boundary = self.heap.len();
copy_term(
CopyBallTerm::new(&mut self.stack, &mut self.heap, &mut self.ball.stub),
CopyBallTerm::new(
&mut self.attr_var_init.attr_var_queue,
&mut self.stack,
&mut self.heap,
&mut self.ball.stub,
),
addr,
AttrVarPolicy::DeepCopy,
);

View File

@@ -159,6 +159,14 @@ impl<'a> CopierTarget for TermCopyingMockWAM<'a> {
self.wam.machine_st.heap.push(val);
}
fn push_attr_var_queue(&mut self, attr_var_loc: usize) {
self.wam
.machine_st
.attr_var_init
.attr_var_queue
.push(attr_var_loc);
}
fn stack(&mut self) -> &mut Stack {
&mut self.wam.machine_st.stack
}

View File

@@ -211,6 +211,15 @@ impl Machine {
)
}
pub fn get_inference_count(&mut self) -> u64 {
self.machine_st
.cwil
.global_count
.clone()
.try_into()
.unwrap()
}
pub fn throw_session_error(&mut self, err: SessionError, key: PredicateKey) {
let err = self.machine_st.session_error(err);
let stub = functor_stub(key.0, key.1);

View File

@@ -27,6 +27,7 @@ use std::io::{Cursor, ErrorKind, Read, Seek, SeekFrom, Write};
use std::mem;
use std::net::{Shutdown, TcpStream};
use std::ops::{Deref, DerefMut};
use std::path::PathBuf;
use std::ptr;
#[cfg(feature = "tls")]
@@ -1837,42 +1838,55 @@ impl MachineState {
}
};
let file = match open_options.open(&*file_spec.as_str()) {
Ok(file) => file,
Err(err) => {
match err.kind() {
ErrorKind::NotFound => {
// 8.11.5.3j)
let stub = functor_stub(atom!("open"), 4);
let mut path = PathBuf::from(&*file_spec.as_str());
let err =
self.existence_error(ExistenceError::SourceSink(self[temp_v!(1)]));
loop {
let file = match open_options.open(&path) {
Ok(file) => file,
Err(err) => {
match err.kind() {
ErrorKind::NotFound => {
// 8.11.5.3j)
let stub = functor_stub(atom!("open"), 4);
return Err(self.error_form(err, stub));
let err =
self.existence_error(ExistenceError::SourceSink(self[temp_v!(1)]));
return Err(self.error_form(err, stub));
}
ErrorKind::PermissionDenied => {
// 8.11.5.3k)
return Err(self.open_permission_error(
self.registers[1],
atom!("open"),
4,
));
}
_ => {
// assume the OS is out of file descriptors.
let stub = functor_stub(atom!("open"), 4);
let err = self.resource_error(ResourceError::OutOfFiles);
return Err(self.error_form(err, stub));
}
}
ErrorKind::PermissionDenied => {
// 8.11.5.3k)
return Err(self.open_permission_error(
self.registers[1],
atom!("open"),
4,
));
}
_ => {
// assume the OS is out of file descriptors.
let stub = functor_stub(atom!("open"), 4);
let err = self.resource_error(ResourceError::OutOfFiles);
}
};
return Err(self.error_form(err, stub));
if path.extension().is_none() {
if let Some(metadata) = file.metadata().ok() {
if metadata.is_dir() {
path.set_extension("pl");
continue;
}
}
}
};
Ok(if is_input_file {
Stream::from_file_as_input(file_spec, file, &mut self.arena)
} else {
Stream::from_file_as_output(file_spec, file, in_append_mode, &mut self.arena)
})
return Ok(if is_input_file {
Stream::from_file_as_input(file_spec, file, &mut self.arena)
} else {
Stream::from_file_as_output(file_spec, file, in_append_mode, &mut self.arena)
});
}
}
}

View File

@@ -1,8 +1,7 @@
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;
@@ -828,8 +827,12 @@ impl MachineState {
) -> usize {
let threshold = self.lifted_heap.len() - lh_offset;
let mut copy_ball_term =
CopyBallTerm::new(&mut self.stack, &mut self.heap, &mut self.lifted_heap);
let mut copy_ball_term = CopyBallTerm::new(
&mut self.attr_var_init.attr_var_queue,
&mut self.stack,
&mut self.heap,
&mut self.lifted_heap,
);
copy_ball_term.push(list_loc_as_cell!(threshold + 1));
copy_ball_term.push(heap_loc_as_cell!(threshold + 3));
@@ -4188,7 +4191,14 @@ impl Machine {
#[cfg(target_arch = "wasm32")]
#[inline(always)]
pub(crate) fn cpu_now(&mut self) {
// TODO
let millisecs = web_sys::window()
.expect("window global object should be available")
.performance()
.expect("performance property in window should be available")
.now();
let secs = float_alloc!(millisecs / 1000.0, self.machine_st.arena);
self.machine_st.unify_f64(secs, self.deref_register(1));
}
#[inline(always)]
@@ -4879,6 +4889,70 @@ impl Machine {
Ok(())
}
#[cfg(not(target_arch = "wasm32"))]
#[inline(always)]
pub(crate) fn js_eval(&mut self) -> CallResult {
unimplemented!()
}
#[cfg(target_arch = "wasm32")]
#[inline(always)]
pub(crate) fn js_eval(&mut self) -> CallResult {
let code = self.deref_register(1);
let result_reg = self.deref_register(2);
if let Some(code) = self.machine_st.value_to_str_like(code) {
match js_sys::eval(&code.as_str()) {
Ok(result) => self.unify_js_value(result, result_reg),
Err(result) => self.unify_js_value(result, result_reg),
};
return Ok(());
}
self.machine_st.fail = true;
Ok(())
}
#[cfg(target_arch = "wasm32")]
fn unify_js_value(&mut self, result: wasm_bindgen::JsValue, result_reg: HeapCellValue) {
match result.as_bool() {
Some(result) => match result {
true => self.machine_st.unify_atom(atom!("true"), result_reg),
false => self.machine_st.unify_atom(atom!("false"), result_reg),
},
None => match result.as_f64() {
Some(result) => {
let n = float_alloc!(result, self.machine_st.arena);
self.machine_st.unify_f64(n, result_reg);
}
None => match result.as_string() {
Some(result) => {
let result = AtomTable::build_with(&self.machine_st.atom_tbl, &result);
self.machine_st.unify_complete_string(result, result_reg);
}
None => {
if result.is_null() {
self.machine_st.unify_atom(atom!("null"), result_reg);
} else if result.is_undefined() {
self.machine_st.unify_atom(atom!("undefined"), result_reg);
} else if result.is_symbol() {
self.machine_st.unify_atom(atom!("js_symbol"), result_reg);
} else if result.is_object() {
self.machine_st.unify_atom(atom!("js_object"), result_reg);
} else if result.is_array() {
self.machine_st.unify_atom(atom!("js_array"), result_reg);
} else if result.is_function() {
self.machine_st.unify_atom(atom!("js_function"), result_reg);
} else if result.is_bigint() {
self.machine_st.unify_atom(atom!("js_bigint"), result_reg);
} else {
self.machine_st
.unify_atom(atom!("js_unknown_type"), result_reg);
}
}
},
},
}
}
#[inline(always)]
pub(crate) fn current_time(&mut self) {
let timestamp = self.systemtime_to_timestamp(SystemTime::now());
@@ -5516,11 +5590,8 @@ impl Machine {
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);
@@ -5531,21 +5602,24 @@ impl Machine {
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);
@@ -5671,7 +5745,6 @@ impl Machine {
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;
}
}
@@ -6791,6 +6864,7 @@ impl Machine {
copy_term(
CopyBallTerm::new(
&mut self.machine_st.attr_var_init.attr_var_queue,
&mut self.machine_st.stack,
&mut self.machine_st.heap,
&mut ball.stub,