Merge branch 'master' into library-use-case
# Conflicts: # Cargo.lock # Cargo.toml # src/http.rs # src/machine/mock_wam.rs # src/machine/mod.rs # src/machine/system_calls.rs
This commit is contained in:
@@ -1,7 +1,5 @@
|
||||
use dashu::base::Abs;
|
||||
use dashu::base::DivRem;
|
||||
use dashu::base::Gcd;
|
||||
use dashu::integer::IBig;
|
||||
use divrem::*;
|
||||
use num_order::NumOrd;
|
||||
|
||||
@@ -562,7 +560,7 @@ pub(crate) fn rdiv(
|
||||
r1: TypedArenaPtr<Rational>,
|
||||
r2: TypedArenaPtr<Rational>,
|
||||
) -> Result<Rational, MachineStubGen> {
|
||||
if &*r2 == &Rational::from(0) {
|
||||
if r2.is_zero() {
|
||||
let stub_gen = || {
|
||||
let rdiv_atom = atom!("rdiv");
|
||||
functor_stub(rdiv_atom, 2)
|
||||
@@ -596,7 +594,7 @@ pub(crate) fn idiv(n1: Number, n2: Number, arena: &mut Arena) -> Result<Number,
|
||||
}
|
||||
}
|
||||
(Number::Fixnum(n1), Number::Integer(n2)) => {
|
||||
if (&*n2).num_eq(&0) {
|
||||
if n2.is_zero() {
|
||||
Err(zero_divisor_eval_error(stub_gen))
|
||||
} else {
|
||||
Ok(Number::arena_from(Integer::from(n1) / &*n2, arena))
|
||||
@@ -610,13 +608,10 @@ pub(crate) fn idiv(n1: Number, n2: Number, arena: &mut Arena) -> Result<Number,
|
||||
}
|
||||
}
|
||||
(Number::Integer(n1), Number::Integer(n2)) => {
|
||||
if (&*n2).num_eq(&0) {
|
||||
if n2.is_zero() {
|
||||
Err(zero_divisor_eval_error(stub_gen))
|
||||
} else {
|
||||
Ok(Number::arena_from(
|
||||
<(Integer, Integer)>::from((&*n1).div_rem(&*n2)).0,
|
||||
arena,
|
||||
))
|
||||
Ok(Number::arena_from(&*n1 / &*n2, arena))
|
||||
}
|
||||
}
|
||||
(Number::Fixnum(_), n2) | (Number::Integer(_), n2) => {
|
||||
@@ -853,6 +848,16 @@ pub(crate) fn modulus(x: Number, y: Number, arena: &mut Arena) -> Result<Number,
|
||||
functor_stub(mod_atom, 2)
|
||||
};
|
||||
|
||||
fn ibig_rem_floor(n1: &Integer, n2: &Integer) -> Integer {
|
||||
if n1 > &Integer::ZERO && n2 < &Integer::ZERO {
|
||||
((n1 - Integer::ONE) / n2) - Integer::ONE
|
||||
} else if n1 < &Integer::ZERO && n2 > &Integer::ZERO {
|
||||
((n1 + Integer::ONE) / n2) - Integer::ONE
|
||||
} else {
|
||||
n1 / n2
|
||||
}
|
||||
}
|
||||
|
||||
match (x, y) {
|
||||
(Number::Fixnum(n1), Number::Fixnum(n2)) => {
|
||||
let n2_i = n2.get_num();
|
||||
@@ -865,14 +870,11 @@ pub(crate) fn modulus(x: Number, y: Number, arena: &mut Arena) -> Result<Number,
|
||||
}
|
||||
}
|
||||
(Number::Fixnum(n1), Number::Integer(n2)) => {
|
||||
if (&*n2).num_eq(&0) {
|
||||
if n2.is_zero() {
|
||||
Err(zero_divisor_eval_error(stub_gen))
|
||||
} else {
|
||||
let n1 = Integer::from(n1.get_num());
|
||||
Ok(Number::arena_from(
|
||||
<(Integer, Integer)>::from(n1.div_rem(&*n2)).1,
|
||||
arena,
|
||||
))
|
||||
Ok(Number::arena_from(ibig_rem_floor(&n1, &*n2), arena))
|
||||
}
|
||||
}
|
||||
(Number::Integer(n1), Number::Fixnum(n2)) => {
|
||||
@@ -882,20 +884,14 @@ pub(crate) fn modulus(x: Number, y: Number, arena: &mut Arena) -> Result<Number,
|
||||
Err(zero_divisor_eval_error(stub_gen))
|
||||
} else {
|
||||
let n2 = Integer::from(n2_i);
|
||||
Ok(Number::arena_from(
|
||||
<(Integer, Integer)>::from((&*n1).div_rem(&n2)).1,
|
||||
arena,
|
||||
))
|
||||
Ok(Number::arena_from(ibig_rem_floor(&*n1, &n2), arena))
|
||||
}
|
||||
}
|
||||
(Number::Integer(x), Number::Integer(y)) => {
|
||||
if (&*y).num_eq(&0) {
|
||||
(Number::Integer(n1), Number::Integer(n2)) => {
|
||||
if n2.is_zero() {
|
||||
Err(zero_divisor_eval_error(stub_gen))
|
||||
} else {
|
||||
Ok(Number::arena_from(
|
||||
<(Integer, Integer)>::from((&*x).div_rem(&*y)).1,
|
||||
arena,
|
||||
))
|
||||
Ok(Number::arena_from(ibig_rem_floor(&*n1, &*n2), arena))
|
||||
}
|
||||
}
|
||||
(Number::Integer(_), n2) | (Number::Fixnum(_), n2) => {
|
||||
@@ -923,7 +919,7 @@ pub(crate) fn remainder(x: Number, y: Number, arena: &mut Arena) -> Result<Numbe
|
||||
}
|
||||
}
|
||||
(Number::Fixnum(n1), Number::Integer(n2)) => {
|
||||
if (&*n2).num_eq(&0) {
|
||||
if n2.is_zero() {
|
||||
Err(zero_divisor_eval_error(stub_gen))
|
||||
} else {
|
||||
let n1 = Integer::from(n1.get_num());
|
||||
@@ -941,7 +937,7 @@ pub(crate) fn remainder(x: Number, y: Number, arena: &mut Arena) -> Result<Numbe
|
||||
}
|
||||
}
|
||||
(Number::Integer(n1), Number::Integer(n2)) => {
|
||||
if (&*n2).num_eq(&0) {
|
||||
if n2.is_zero() {
|
||||
Err(zero_divisor_eval_error(stub_gen))
|
||||
} else {
|
||||
Ok(Number::arena_from(Integer::from(&*n1 % &*n2), arena))
|
||||
@@ -968,7 +964,7 @@ pub(crate) fn gcd(n1: Number, n2: Number, arena: &mut Arena) -> Result<Number, M
|
||||
if let Some(result) = isize_gcd(n1_i, n2_i) {
|
||||
Ok(Number::arena_from(result, arena))
|
||||
} else {
|
||||
let value: IBig = Integer::from(n1_i).gcd(&Integer::from(n2_i)).into();
|
||||
let value: Integer = Integer::from(n1_i).gcd(&Integer::from(n2_i)).into();
|
||||
Ok(Number::arena_from(value, arena))
|
||||
}
|
||||
}
|
||||
@@ -978,9 +974,9 @@ pub(crate) fn gcd(n1: Number, n2: Number, arena: &mut Arena) -> Result<Number, M
|
||||
Ok(Number::arena_from(Integer::from(n2_clone.gcd(&n1)), arena))
|
||||
}
|
||||
(Number::Integer(n1), Number::Integer(n2)) => {
|
||||
let n1_clone: Integer = (*n1).clone();
|
||||
let n2: isize = (&*n2).try_into().unwrap();
|
||||
Ok(Number::arena_from(Integer::from(n1_clone.gcd(&Integer::from(n2))) as IBig, arena))
|
||||
let value: Integer = (&*n1).gcd(&Integer::from(n2)).into();
|
||||
Ok(Number::arena_from(value, arena))
|
||||
}
|
||||
(Number::Float(f), _) | (_, Number::Float(f)) => {
|
||||
let n = Number::Float(f);
|
||||
@@ -1212,7 +1208,8 @@ impl MachineState {
|
||||
value: HeapCellValue,
|
||||
) -> Result<Number, MachineStub> {
|
||||
let stub_gen = || functor_stub(atom!("is"), 2);
|
||||
let mut iter = stackful_post_order_iter(&mut self.heap, &mut self.stack, value);
|
||||
let mut iter = stackful_post_order_iter::<NonListElider>
|
||||
(&mut self.heap, &mut self.stack, value);
|
||||
|
||||
while let Some(value) = iter.next() {
|
||||
if value.get_forwarding_bit() {
|
||||
|
||||
@@ -133,7 +133,8 @@ impl MachineState {
|
||||
let mut seen_set = IndexSet::new();
|
||||
let mut seen_vars = vec![];
|
||||
|
||||
let mut iter = stackful_preorder_iter(&mut self.heap, &mut self.stack, cell);
|
||||
let mut iter = stackful_preorder_iter::<NonListElider>
|
||||
(&mut self.heap, &mut self.stack, cell);
|
||||
|
||||
while let Some(value) = iter.next() {
|
||||
read_heap_cell!(value,
|
||||
|
||||
@@ -2331,7 +2331,7 @@ impl Machine {
|
||||
let mut loader: Loader<'_, InlineLoadState<'_>> =
|
||||
Loader::new(self, InlineTermStream {});
|
||||
|
||||
let term = loader.read_term_from_heap(term_loc)?;
|
||||
let term = loader.read_term_from_heap(term_loc);
|
||||
let clause = build_rule_body(vars, term);
|
||||
|
||||
let settings = CodeGenSettings {
|
||||
|
||||
@@ -34,6 +34,15 @@ macro_rules! try_or_throw {
|
||||
}};
|
||||
}
|
||||
|
||||
macro_rules! increment_call_count {
|
||||
($s:expr) => {{
|
||||
if !($s.increment_call_count_fn)(&mut $s) {
|
||||
$s.backtrack();
|
||||
continue;
|
||||
}
|
||||
}};
|
||||
}
|
||||
|
||||
macro_rules! try_or_throw_gen {
|
||||
($s:expr, $e:expr) => {{
|
||||
match $e {
|
||||
@@ -1096,12 +1105,7 @@ impl Machine {
|
||||
self.trust_me();
|
||||
}
|
||||
|
||||
try_or_throw!(
|
||||
self.machine_st,
|
||||
(self.machine_st.increment_call_count_fn)(
|
||||
&mut self.machine_st
|
||||
)
|
||||
);
|
||||
increment_call_count!(self.machine_st);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1174,12 +1178,7 @@ impl Machine {
|
||||
self.trust_me();
|
||||
}
|
||||
|
||||
try_or_throw!(
|
||||
self.machine_st,
|
||||
(self.machine_st.increment_call_count_fn)(
|
||||
&mut self.machine_st
|
||||
)
|
||||
);
|
||||
increment_call_count!(self.machine_st);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1205,19 +1204,11 @@ impl Machine {
|
||||
}
|
||||
&Instruction::RetryMeElse(offset) => {
|
||||
self.retry_me_else(offset);
|
||||
|
||||
try_or_throw!(
|
||||
self.machine_st,
|
||||
(self.machine_st.increment_call_count_fn)(&mut self.machine_st)
|
||||
);
|
||||
increment_call_count!(self.machine_st);
|
||||
}
|
||||
&Instruction::TrustMe(_) => {
|
||||
self.trust_me();
|
||||
|
||||
try_or_throw!(
|
||||
self.machine_st,
|
||||
(self.machine_st.increment_call_count_fn)(&mut self.machine_st)
|
||||
);
|
||||
increment_call_count!(self.machine_st);
|
||||
}
|
||||
&Instruction::NeckCut => {
|
||||
self.machine_st.neck_cut();
|
||||
@@ -1521,11 +1512,7 @@ impl Machine {
|
||||
if self.machine_st.is_cyclic_term(addr) {
|
||||
self.machine_st.backtrack();
|
||||
} else {
|
||||
try_or_throw!(
|
||||
self.machine_st,
|
||||
(self.machine_st.increment_call_count_fn)(&mut self.machine_st)
|
||||
);
|
||||
|
||||
increment_call_count!(self.machine_st);
|
||||
self.machine_st.p += 1;
|
||||
}
|
||||
}
|
||||
@@ -1535,11 +1522,7 @@ impl Machine {
|
||||
if self.machine_st.is_cyclic_term(addr) {
|
||||
self.machine_st.backtrack();
|
||||
} else {
|
||||
try_or_throw!(
|
||||
self.machine_st,
|
||||
(self.machine_st.increment_call_count_fn)(&mut self.machine_st)
|
||||
);
|
||||
|
||||
increment_call_count!(self.machine_st);
|
||||
self.machine_st.p = self.machine_st.cp;
|
||||
}
|
||||
}
|
||||
@@ -1549,11 +1532,7 @@ impl Machine {
|
||||
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)
|
||||
);
|
||||
|
||||
increment_call_count!(self.machine_st);
|
||||
self.machine_st.p += 1;
|
||||
}
|
||||
}
|
||||
@@ -1563,11 +1542,7 @@ impl Machine {
|
||||
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)
|
||||
);
|
||||
|
||||
increment_call_count!(self.machine_st);
|
||||
self.machine_st.p = self.machine_st.cp;
|
||||
}
|
||||
}
|
||||
@@ -1577,11 +1552,7 @@ impl Machine {
|
||||
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)
|
||||
);
|
||||
|
||||
increment_call_count!(self.machine_st);
|
||||
self.machine_st.p += 1;
|
||||
}
|
||||
}
|
||||
@@ -1591,11 +1562,7 @@ impl Machine {
|
||||
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)
|
||||
);
|
||||
|
||||
increment_call_count!(self.machine_st);
|
||||
self.machine_st.p = self.machine_st.cp;
|
||||
}
|
||||
}
|
||||
@@ -1605,11 +1572,7 @@ impl Machine {
|
||||
|
||||
if let Some(Ordering::Greater) = compare_term_test!(self.machine_st, a1, a2)
|
||||
{
|
||||
try_or_throw!(
|
||||
self.machine_st,
|
||||
(self.machine_st.increment_call_count_fn)(&mut self.machine_st)
|
||||
);
|
||||
|
||||
increment_call_count!(self.machine_st);
|
||||
self.machine_st.p += 1;
|
||||
} else {
|
||||
self.machine_st.backtrack();
|
||||
@@ -1621,11 +1584,7 @@ impl Machine {
|
||||
|
||||
if let Some(Ordering::Greater) = compare_term_test!(self.machine_st, a1, a2)
|
||||
{
|
||||
try_or_throw!(
|
||||
self.machine_st,
|
||||
(self.machine_st.increment_call_count_fn)(&mut self.machine_st)
|
||||
);
|
||||
|
||||
increment_call_count!(self.machine_st);
|
||||
self.machine_st.p = self.machine_st.cp;
|
||||
} else {
|
||||
self.machine_st.backtrack();
|
||||
@@ -1636,11 +1595,7 @@ impl Machine {
|
||||
let a2 = self.machine_st.registers[2];
|
||||
|
||||
if let Some(Ordering::Less) = compare_term_test!(self.machine_st, a1, a2) {
|
||||
try_or_throw!(
|
||||
self.machine_st,
|
||||
(self.machine_st.increment_call_count_fn)(&mut self.machine_st)
|
||||
);
|
||||
|
||||
increment_call_count!(self.machine_st);
|
||||
self.machine_st.p += 1;
|
||||
} else {
|
||||
self.machine_st.backtrack();
|
||||
@@ -1651,11 +1606,7 @@ impl Machine {
|
||||
let a2 = self.machine_st.registers[2];
|
||||
|
||||
if let Some(Ordering::Less) = compare_term_test!(self.machine_st, a1, a2) {
|
||||
try_or_throw!(
|
||||
self.machine_st,
|
||||
(self.machine_st.increment_call_count_fn)(&mut self.machine_st)
|
||||
);
|
||||
|
||||
increment_call_count!(self.machine_st);
|
||||
self.machine_st.p = self.machine_st.cp;
|
||||
} else {
|
||||
self.machine_st.backtrack();
|
||||
@@ -1667,11 +1618,7 @@ impl Machine {
|
||||
|
||||
match compare_term_test!(self.machine_st, a1, a2) {
|
||||
Some(Ordering::Greater | Ordering::Equal) => {
|
||||
try_or_throw!(
|
||||
self.machine_st,
|
||||
(self.machine_st.increment_call_count_fn)(&mut self.machine_st)
|
||||
);
|
||||
|
||||
increment_call_count!(self.machine_st);
|
||||
self.machine_st.p += 1;
|
||||
}
|
||||
_ => {
|
||||
@@ -1685,11 +1632,7 @@ impl Machine {
|
||||
|
||||
match compare_term_test!(self.machine_st, a1, a2) {
|
||||
Some(Ordering::Greater | Ordering::Equal) => {
|
||||
try_or_throw!(
|
||||
self.machine_st,
|
||||
(self.machine_st.increment_call_count_fn)(&mut self.machine_st)
|
||||
);
|
||||
|
||||
increment_call_count!(self.machine_st);
|
||||
self.machine_st.p = self.machine_st.cp;
|
||||
}
|
||||
_ => {
|
||||
@@ -1703,11 +1646,7 @@ impl Machine {
|
||||
|
||||
match compare_term_test!(self.machine_st, a1, a2) {
|
||||
Some(Ordering::Less | Ordering::Equal) => {
|
||||
try_or_throw!(
|
||||
self.machine_st,
|
||||
(self.machine_st.increment_call_count_fn)(&mut self.machine_st)
|
||||
);
|
||||
|
||||
increment_call_count!(self.machine_st);
|
||||
self.machine_st.p += 1;
|
||||
}
|
||||
_ => {
|
||||
@@ -1721,11 +1660,7 @@ impl Machine {
|
||||
|
||||
match compare_term_test!(self.machine_st, a1, a2) {
|
||||
Some(Ordering::Less | Ordering::Equal) => {
|
||||
try_or_throw!(
|
||||
self.machine_st,
|
||||
(self.machine_st.increment_call_count_fn)(&mut self.machine_st)
|
||||
);
|
||||
|
||||
increment_call_count!(self.machine_st);
|
||||
self.machine_st.p = self.machine_st.cp;
|
||||
}
|
||||
_ => {
|
||||
@@ -1739,11 +1674,7 @@ impl Machine {
|
||||
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)
|
||||
);
|
||||
|
||||
increment_call_count!(self.machine_st);
|
||||
self.machine_st.p += 1;
|
||||
}
|
||||
}
|
||||
@@ -1753,11 +1684,7 @@ impl Machine {
|
||||
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)
|
||||
);
|
||||
|
||||
increment_call_count!(self.machine_st);
|
||||
self.machine_st.p = self.machine_st.cp;
|
||||
}
|
||||
}
|
||||
@@ -1768,11 +1695,7 @@ impl Machine {
|
||||
if self.machine_st.eq_test(a1, a2) {
|
||||
self.machine_st.backtrack();
|
||||
} else {
|
||||
try_or_throw!(
|
||||
self.machine_st,
|
||||
(self.machine_st.increment_call_count_fn)(&mut self.machine_st)
|
||||
);
|
||||
|
||||
increment_call_count!(self.machine_st);
|
||||
self.machine_st.p += 1;
|
||||
}
|
||||
}
|
||||
@@ -1783,11 +1706,7 @@ impl Machine {
|
||||
if self.machine_st.eq_test(a1, a2) {
|
||||
self.machine_st.backtrack();
|
||||
} else {
|
||||
try_or_throw!(
|
||||
self.machine_st,
|
||||
(self.machine_st.increment_call_count_fn)(&mut self.machine_st)
|
||||
);
|
||||
|
||||
increment_call_count!(self.machine_st);
|
||||
self.machine_st.p = self.machine_st.cp;
|
||||
}
|
||||
}
|
||||
@@ -1795,11 +1714,7 @@ impl Machine {
|
||||
if self.machine_st.ground_test() {
|
||||
self.machine_st.backtrack();
|
||||
} else {
|
||||
try_or_throw!(
|
||||
self.machine_st,
|
||||
(self.machine_st.increment_call_count_fn)(&mut self.machine_st)
|
||||
);
|
||||
|
||||
increment_call_count!(self.machine_st);
|
||||
self.machine_st.p += 1;
|
||||
}
|
||||
}
|
||||
@@ -1807,11 +1722,7 @@ impl Machine {
|
||||
if self.machine_st.ground_test() {
|
||||
self.machine_st.backtrack();
|
||||
} else {
|
||||
try_or_throw!(
|
||||
self.machine_st,
|
||||
(self.machine_st.increment_call_count_fn)(&mut self.machine_st)
|
||||
);
|
||||
|
||||
increment_call_count!(self.machine_st);
|
||||
self.machine_st.p = self.machine_st.cp;
|
||||
}
|
||||
}
|
||||
@@ -1821,11 +1732,7 @@ impl Machine {
|
||||
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)
|
||||
);
|
||||
|
||||
increment_call_count!(self.machine_st);
|
||||
self.machine_st.p += 1;
|
||||
}
|
||||
}
|
||||
@@ -1835,11 +1742,7 @@ impl Machine {
|
||||
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)
|
||||
);
|
||||
|
||||
increment_call_count!(self.machine_st);
|
||||
self.machine_st.p = self.machine_st.cp;
|
||||
}
|
||||
}
|
||||
@@ -1850,11 +1753,7 @@ impl Machine {
|
||||
if let Some(Ordering::Equal) = compare_term_test!(self.machine_st, a1, a2) {
|
||||
self.machine_st.backtrack();
|
||||
} else {
|
||||
try_or_throw!(
|
||||
self.machine_st,
|
||||
(self.machine_st.increment_call_count_fn)(&mut self.machine_st)
|
||||
);
|
||||
|
||||
increment_call_count!(self.machine_st);
|
||||
self.machine_st.p += 1;
|
||||
}
|
||||
}
|
||||
@@ -1865,11 +1764,7 @@ impl Machine {
|
||||
if let Some(Ordering::Equal) = compare_term_test!(self.machine_st, a1, a2) {
|
||||
self.machine_st.backtrack();
|
||||
} else {
|
||||
try_or_throw!(
|
||||
self.machine_st,
|
||||
(self.machine_st.increment_call_count_fn)(&mut self.machine_st)
|
||||
);
|
||||
|
||||
increment_call_count!(self.machine_st);
|
||||
self.machine_st.p = self.machine_st.cp;
|
||||
}
|
||||
}
|
||||
@@ -1879,11 +1774,7 @@ impl Machine {
|
||||
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)
|
||||
);
|
||||
|
||||
increment_call_count!(self.machine_st);
|
||||
self.machine_st.p += 1;
|
||||
}
|
||||
}
|
||||
@@ -1893,11 +1784,7 @@ impl Machine {
|
||||
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)
|
||||
);
|
||||
|
||||
increment_call_count!(self.machine_st);
|
||||
self.machine_st.p = self.machine_st.cp;
|
||||
}
|
||||
}
|
||||
@@ -1910,11 +1797,7 @@ impl Machine {
|
||||
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)
|
||||
);
|
||||
|
||||
increment_call_count!(self.machine_st);
|
||||
self.machine_st.p += 1;
|
||||
}
|
||||
}
|
||||
@@ -1927,11 +1810,7 @@ impl Machine {
|
||||
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)
|
||||
);
|
||||
|
||||
increment_call_count!(self.machine_st);
|
||||
self.machine_st.p = self.machine_st.cp;
|
||||
}
|
||||
}
|
||||
@@ -1944,11 +1823,7 @@ impl Machine {
|
||||
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)
|
||||
);
|
||||
|
||||
increment_call_count!(self.machine_st);
|
||||
self.machine_st.p += 1;
|
||||
}
|
||||
}
|
||||
@@ -1961,11 +1836,7 @@ impl Machine {
|
||||
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)
|
||||
);
|
||||
|
||||
increment_call_count!(self.machine_st);
|
||||
self.machine_st.p = self.machine_st.cp;
|
||||
}
|
||||
}
|
||||
@@ -1975,11 +1846,7 @@ impl Machine {
|
||||
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)
|
||||
);
|
||||
|
||||
increment_call_count!(self.machine_st);
|
||||
self.machine_st.p += 1;
|
||||
}
|
||||
}
|
||||
@@ -1989,11 +1856,7 @@ impl Machine {
|
||||
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)
|
||||
);
|
||||
|
||||
increment_call_count!(self.machine_st);
|
||||
self.machine_st.p = self.machine_st.cp;
|
||||
}
|
||||
}
|
||||
@@ -2003,11 +1866,7 @@ impl Machine {
|
||||
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)
|
||||
);
|
||||
|
||||
increment_call_count!(self.machine_st);
|
||||
self.machine_st.p += 1;
|
||||
}
|
||||
}
|
||||
@@ -2017,11 +1876,7 @@ impl Machine {
|
||||
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)
|
||||
);
|
||||
|
||||
increment_call_count!(self.machine_st);
|
||||
self.machine_st.p = self.machine_st.cp;
|
||||
}
|
||||
}
|
||||
@@ -2039,10 +1894,7 @@ impl Machine {
|
||||
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)
|
||||
);
|
||||
increment_call_count!(self.machine_st);
|
||||
}
|
||||
}
|
||||
&Instruction::ExecuteN(arity) => {
|
||||
@@ -2059,10 +1911,7 @@ impl Machine {
|
||||
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)
|
||||
);
|
||||
increment_call_count!(self.machine_st);
|
||||
}
|
||||
}
|
||||
&Instruction::DefaultCallN(arity) => {
|
||||
@@ -2101,11 +1950,7 @@ impl Machine {
|
||||
|
||||
match n1.cmp(&n2) {
|
||||
Ordering::Less | Ordering::Equal => {
|
||||
try_or_throw!(
|
||||
self.machine_st,
|
||||
(self.machine_st.increment_call_count_fn)(&mut self.machine_st)
|
||||
);
|
||||
|
||||
increment_call_count!(self.machine_st);
|
||||
self.machine_st.p += 1;
|
||||
}
|
||||
_ => {
|
||||
@@ -2119,11 +1964,7 @@ impl Machine {
|
||||
|
||||
match n1.cmp(&n2) {
|
||||
Ordering::Less | Ordering::Equal => {
|
||||
try_or_throw!(
|
||||
self.machine_st,
|
||||
(self.machine_st.increment_call_count_fn)(&mut self.machine_st)
|
||||
);
|
||||
|
||||
increment_call_count!(self.machine_st);
|
||||
self.machine_st.p = self.machine_st.cp;
|
||||
}
|
||||
_ => {
|
||||
@@ -2137,11 +1978,7 @@ impl Machine {
|
||||
|
||||
match n1.cmp(&n2) {
|
||||
Ordering::Equal => {
|
||||
try_or_throw!(
|
||||
self.machine_st,
|
||||
(self.machine_st.increment_call_count_fn)(&mut self.machine_st)
|
||||
);
|
||||
|
||||
increment_call_count!(self.machine_st);
|
||||
self.machine_st.p += 1;
|
||||
}
|
||||
_ => {
|
||||
@@ -2155,11 +1992,7 @@ impl Machine {
|
||||
|
||||
match n1.cmp(&n2) {
|
||||
Ordering::Equal => {
|
||||
try_or_throw!(
|
||||
self.machine_st,
|
||||
(self.machine_st.increment_call_count_fn)(&mut self.machine_st)
|
||||
);
|
||||
|
||||
increment_call_count!(self.machine_st);
|
||||
self.machine_st.p = self.machine_st.cp;
|
||||
}
|
||||
_ => {
|
||||
@@ -2176,11 +2009,7 @@ impl Machine {
|
||||
self.machine_st.backtrack();
|
||||
}
|
||||
_ => {
|
||||
try_or_throw!(
|
||||
self.machine_st,
|
||||
(self.machine_st.increment_call_count_fn)(&mut self.machine_st)
|
||||
);
|
||||
|
||||
increment_call_count!(self.machine_st);
|
||||
self.machine_st.p += 1;
|
||||
}
|
||||
}
|
||||
@@ -2194,11 +2023,7 @@ impl Machine {
|
||||
self.machine_st.backtrack();
|
||||
}
|
||||
_ => {
|
||||
try_or_throw!(
|
||||
self.machine_st,
|
||||
(self.machine_st.increment_call_count_fn)(&mut self.machine_st)
|
||||
);
|
||||
|
||||
increment_call_count!(self.machine_st);
|
||||
self.machine_st.p = self.machine_st.cp;
|
||||
}
|
||||
}
|
||||
@@ -2209,11 +2034,7 @@ impl Machine {
|
||||
|
||||
match n1.cmp(&n2) {
|
||||
Ordering::Greater | Ordering::Equal => {
|
||||
try_or_throw!(
|
||||
self.machine_st,
|
||||
(self.machine_st.increment_call_count_fn)(&mut self.machine_st)
|
||||
);
|
||||
|
||||
increment_call_count!(self.machine_st);
|
||||
self.machine_st.p += 1;
|
||||
}
|
||||
_ => {
|
||||
@@ -2227,11 +2048,7 @@ impl Machine {
|
||||
|
||||
match n1.cmp(&n2) {
|
||||
Ordering::Greater | Ordering::Equal => {
|
||||
try_or_throw!(
|
||||
self.machine_st,
|
||||
(self.machine_st.increment_call_count_fn)(&mut self.machine_st)
|
||||
);
|
||||
|
||||
increment_call_count!(self.machine_st);
|
||||
self.machine_st.p = self.machine_st.cp;
|
||||
}
|
||||
_ => {
|
||||
@@ -2245,11 +2062,7 @@ impl Machine {
|
||||
|
||||
match n1.cmp(&n2) {
|
||||
Ordering::Greater => {
|
||||
try_or_throw!(
|
||||
self.machine_st,
|
||||
(self.machine_st.increment_call_count_fn)(&mut self.machine_st)
|
||||
);
|
||||
|
||||
increment_call_count!(self.machine_st);
|
||||
self.machine_st.p += 1;
|
||||
}
|
||||
_ => {
|
||||
@@ -2263,11 +2076,7 @@ impl Machine {
|
||||
|
||||
match n1.cmp(&n2) {
|
||||
Ordering::Greater => {
|
||||
try_or_throw!(
|
||||
self.machine_st,
|
||||
(self.machine_st.increment_call_count_fn)(&mut self.machine_st)
|
||||
);
|
||||
|
||||
increment_call_count!(self.machine_st);
|
||||
self.machine_st.p = self.machine_st.cp;
|
||||
}
|
||||
_ => {
|
||||
@@ -2281,11 +2090,7 @@ impl Machine {
|
||||
|
||||
match n1.cmp(&n2) {
|
||||
Ordering::Less => {
|
||||
try_or_throw!(
|
||||
self.machine_st,
|
||||
(self.machine_st.increment_call_count_fn)(&mut self.machine_st)
|
||||
);
|
||||
|
||||
increment_call_count!(self.machine_st);
|
||||
self.machine_st.p += 1;
|
||||
}
|
||||
_ => {
|
||||
@@ -2299,11 +2104,7 @@ impl Machine {
|
||||
|
||||
match n1.cmp(&n2) {
|
||||
Ordering::Less => {
|
||||
try_or_throw!(
|
||||
self.machine_st,
|
||||
(self.machine_st.increment_call_count_fn)(&mut self.machine_st)
|
||||
);
|
||||
|
||||
increment_call_count!(self.machine_st);
|
||||
self.machine_st.p = self.machine_st.cp;
|
||||
}
|
||||
_ => {
|
||||
@@ -2878,10 +2679,7 @@ impl Machine {
|
||||
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)
|
||||
);
|
||||
increment_call_count!(self.machine_st);
|
||||
}
|
||||
}
|
||||
&Instruction::ExecuteNamed(arity, name, ref idx) => {
|
||||
@@ -2892,10 +2690,7 @@ impl Machine {
|
||||
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)
|
||||
);
|
||||
increment_call_count!(self.machine_st);
|
||||
}
|
||||
}
|
||||
&Instruction::DefaultCallNamed(arity, name, ref idx) => {
|
||||
@@ -3224,26 +3019,14 @@ impl Machine {
|
||||
}
|
||||
&IndexedChoiceInstruction::Retry(l) => {
|
||||
self.retry(l);
|
||||
|
||||
try_or_throw!(
|
||||
self.machine_st,
|
||||
(self.machine_st.increment_call_count_fn)(
|
||||
&mut self.machine_st
|
||||
)
|
||||
);
|
||||
increment_call_count!(self.machine_st);
|
||||
}
|
||||
&IndexedChoiceInstruction::DefaultRetry(l) => {
|
||||
self.retry(l);
|
||||
}
|
||||
&IndexedChoiceInstruction::Trust(l) => {
|
||||
self.trust(l);
|
||||
|
||||
try_or_throw!(
|
||||
self.machine_st,
|
||||
(self.machine_st.increment_call_count_fn)(
|
||||
&mut self.machine_st
|
||||
)
|
||||
);
|
||||
increment_call_count!(self.machine_st);
|
||||
}
|
||||
&IndexedChoiceInstruction::DefaultTrust(l) => {
|
||||
self.trust(l);
|
||||
@@ -3318,38 +3101,16 @@ impl Machine {
|
||||
// this is true iff ii + 1 < len.
|
||||
Some(_) => {
|
||||
self.retry(offset);
|
||||
|
||||
try_or_throw!(
|
||||
self.machine_st,
|
||||
(self
|
||||
.machine_st
|
||||
.increment_call_count_fn)(
|
||||
&mut self.machine_st
|
||||
)
|
||||
);
|
||||
increment_call_count!(self.machine_st);
|
||||
}
|
||||
_ => {
|
||||
self.trust(offset);
|
||||
|
||||
try_or_throw!(
|
||||
self.machine_st,
|
||||
(self
|
||||
.machine_st
|
||||
.increment_call_count_fn)(
|
||||
&mut self.machine_st
|
||||
)
|
||||
);
|
||||
increment_call_count!(self.machine_st);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
self.trust(offset);
|
||||
|
||||
try_or_throw!(
|
||||
self.machine_st,
|
||||
(self.machine_st.increment_call_count_fn)(
|
||||
&mut self.machine_st
|
||||
)
|
||||
);
|
||||
increment_call_count!(self.machine_st);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5484,6 +5245,14 @@ impl Machine {
|
||||
self.get_db_refs();
|
||||
step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
|
||||
}
|
||||
&Instruction::CallInferenceLimitExceeded => {
|
||||
self.inference_limit_exceeded();
|
||||
step_or_fail!(self, self.machine_st.p += 1);
|
||||
}
|
||||
&Instruction::ExecuteInferenceLimitExceeded => {
|
||||
self.inference_limit_exceeded();
|
||||
step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5499,6 +5268,17 @@ impl Machine {
|
||||
if interruption {
|
||||
self.machine_st.throw_interrupt_exception();
|
||||
self.machine_st.backtrack();
|
||||
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
let runtime = tokio::runtime::Runtime::new().unwrap();
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
let runtime = tokio::runtime::Builder::new_current_thread()
|
||||
.enable_all()
|
||||
.build()
|
||||
.unwrap();
|
||||
|
||||
let old_runtime = std::mem::replace(&mut self.runtime, runtime);
|
||||
old_runtime.shutdown_background();
|
||||
}
|
||||
}
|
||||
Err(_) => unreachable!(),
|
||||
|
||||
@@ -9,7 +9,7 @@ use crate::parser::ast::*;
|
||||
|
||||
use fxhash::FxBuildHasher;
|
||||
use indexmap::IndexSet;
|
||||
use ref_thread_local::RefThreadLocal;
|
||||
pub use ref_thread_local::RefThreadLocal;
|
||||
|
||||
use std::collections::VecDeque;
|
||||
use std::fs::File;
|
||||
@@ -1004,10 +1004,22 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn add_module(&mut self, module_decl: ModuleDecl, listing_src: ListingSource) {
|
||||
self.reset_in_situ_module(module_decl.clone(), &listing_src);
|
||||
pub(crate) fn add_module(
|
||||
&mut self,
|
||||
module_decl: ModuleDecl,
|
||||
listing_src: ListingSource,
|
||||
) -> Result<(), SessionError> {
|
||||
let module_name = module_decl.name;
|
||||
|
||||
if let Some(module) = self.wam_prelude.indices.modules.get(&module_name) {
|
||||
if let ListingSource::DynamicallyGenerated = module.listing_src {
|
||||
} else {
|
||||
LS::err_on_builtin_module_overwrite(module_name)?;
|
||||
}
|
||||
}
|
||||
|
||||
self.reset_in_situ_module(module_decl.clone(), &listing_src);
|
||||
|
||||
let mut module = match self.wam_prelude.indices.modules.remove(&module_name) {
|
||||
Some(mut module) => {
|
||||
module.listing_src = listing_src;
|
||||
@@ -1045,6 +1057,8 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
|
||||
}
|
||||
|
||||
self.wam_prelude.indices.modules.insert(module_name, module);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(super) fn import_module(&mut self, module_name: Atom) -> Result<(), SessionError> {
|
||||
|
||||
@@ -265,6 +265,10 @@ pub trait LoadState<'a>: Sized {
|
||||
loader: &Loader<'a, Self>,
|
||||
key: PredicateKey,
|
||||
) -> Result<(), SessionError>;
|
||||
|
||||
fn err_on_builtin_module_overwrite(_module_name: Atom) -> Result<(), SessionError> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
pub struct LiveLoadAndMachineState<'a> {
|
||||
@@ -353,6 +357,15 @@ impl<'a> LoadState<'a> for LiveLoadAndMachineState<'a> {
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn err_on_builtin_module_overwrite(module_name: Atom) -> Result<(), SessionError> {
|
||||
if LIBRARIES.borrow().contains_key(&*module_name.as_str()) {
|
||||
Err(SessionError::CannotOverwriteBuiltInModule(module_name))
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> LoadState<'a> for BootstrappingLoadState<'a> {
|
||||
@@ -483,7 +496,7 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn read_term_from_heap(&mut self, r: RegType) -> Result<Term, SessionError> {
|
||||
pub(crate) fn read_term_from_heap(&mut self, r: RegType) -> Term {
|
||||
let machine_st = LS::machine_st(&mut self.payload);
|
||||
let cell = machine_st[r];
|
||||
|
||||
@@ -533,11 +546,13 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
|
||||
self.add_meta_predicate_record(module_name, name, meta_specs);
|
||||
}
|
||||
Declaration::Module(module_decl) => {
|
||||
self.payload.compilation_target = CompilationTarget::Module(module_decl.name);
|
||||
let module_name = module_decl.name;
|
||||
|
||||
self.payload.compilation_target = CompilationTarget::Module(module_name);
|
||||
self.payload.predicates.compilation_target = self.payload.compilation_target;
|
||||
|
||||
let listing_src = self.payload.term_stream.listing_src().clone();
|
||||
self.add_module(module_decl, listing_src);
|
||||
self.add_module(module_decl, listing_src)?;
|
||||
}
|
||||
Declaration::NonCountedBacktracking(name, arity) => {
|
||||
self.payload.non_counted_bt_preds.insert((name, arity));
|
||||
@@ -1074,7 +1089,7 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
|
||||
let machine_st = LS::machine_st(&mut self.payload);
|
||||
let cell = machine_st[r];
|
||||
|
||||
let export_list = machine_st.read_term_from_heap(cell)?;
|
||||
let export_list = machine_st.read_term_from_heap(cell);
|
||||
let atom_tbl = &mut LS::machine_st(&mut self.payload).atom_tbl;
|
||||
let export_list = setup_module_export_list(export_list, &atom_tbl)?;
|
||||
|
||||
@@ -1401,9 +1416,10 @@ impl MachineState {
|
||||
pub(super) fn read_term_from_heap(
|
||||
&mut self,
|
||||
term_addr: HeapCellValue,
|
||||
) -> Result<Term, SessionError> {
|
||||
) -> Term {
|
||||
let mut term_stack = vec![];
|
||||
let mut iter = stackful_post_order_iter(&mut self.heap, &mut self.stack, term_addr);
|
||||
let mut iter = stackful_post_order_iter::<NonListElider>
|
||||
(&mut self.heap, &mut self.stack, term_addr);
|
||||
|
||||
while let Some(addr) = iter.next() {
|
||||
let addr = unmark_cell_bits!(addr);
|
||||
@@ -1494,7 +1510,7 @@ impl MachineState {
|
||||
}
|
||||
|
||||
debug_assert!(term_stack.len() == 1);
|
||||
Ok(term_stack.pop().unwrap())
|
||||
term_stack.pop().unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1636,7 +1652,7 @@ impl Machine {
|
||||
|
||||
let arity = self.deref_register(3);
|
||||
let arity = match Number::try_from(arity) {
|
||||
Ok(Number::Integer(n)) if &*n >= &Integer::from(0) && &*n <= &Integer::from(MAX_ARITY) => {
|
||||
Ok(Number::Integer(n)) if &*n >= &Integer::ZERO && &*n <= &Integer::from(MAX_ARITY) => {
|
||||
let value: usize = (&*n).try_into().unwrap();
|
||||
Ok(value)
|
||||
},
|
||||
@@ -1661,7 +1677,7 @@ impl Machine {
|
||||
let mut loader = self.loader_from_heap_evacuable(temp_v!(2));
|
||||
|
||||
let add_clause = || {
|
||||
let term = loader.read_term_from_heap(temp_v!(1))?;
|
||||
let term = loader.read_term_from_heap(temp_v!(1));
|
||||
|
||||
loader.incremental_compile_clause(
|
||||
(atom!("term_expansion"), 2),
|
||||
@@ -1691,7 +1707,7 @@ impl Machine {
|
||||
};
|
||||
|
||||
let add_clause = || {
|
||||
let term = loader.read_term_from_heap(temp_v!(2))?;
|
||||
let term = loader.read_term_from_heap(temp_v!(2));
|
||||
|
||||
let indexing_arg = match term.name() {
|
||||
Some(atom!(":-")) => term.first_arg().and_then(Term::first_arg),
|
||||
@@ -1849,9 +1865,7 @@ impl Machine {
|
||||
2,
|
||||
)?;
|
||||
|
||||
let path = cell_as_atom!(self
|
||||
.machine_st
|
||||
.store(self.machine_st.deref(self.machine_st.registers[2])));
|
||||
let path = cell_as_atom!(self.deref_register(2));
|
||||
|
||||
self.load_contexts
|
||||
.push(LoadContext::new(&*path.as_str(), stream));
|
||||
@@ -2008,7 +2022,7 @@ impl Machine {
|
||||
loader.payload.compilation_target = compilation_target;
|
||||
|
||||
let head = LiveLoadAndMachineState::machine_st(&mut loader.payload)
|
||||
.read_term_from_heap(head)?;
|
||||
.read_term_from_heap(head);
|
||||
|
||||
let name = if let Some(name) = head.name() {
|
||||
name
|
||||
@@ -2044,7 +2058,7 @@ impl Machine {
|
||||
return LiveLoadAndMachineState::evacuate(loader);
|
||||
}
|
||||
|
||||
let body = loader.read_term_from_heap(temp_v!(3))?;
|
||||
let body = loader.read_term_from_heap(temp_v!(3));
|
||||
|
||||
let asserted_clause = Term::Clause(
|
||||
Cell::default(),
|
||||
@@ -2482,7 +2496,7 @@ impl<'a> Loader<'a, LiveLoadAndMachineState<'a>> {
|
||||
self.payload.predicates.compilation_target = compilation_target;
|
||||
}
|
||||
|
||||
let term = self.read_term_from_heap(term_reg)?;
|
||||
let term = self.read_term_from_heap(term_reg);
|
||||
|
||||
self.add_clause_clause_if_dynamic(&term)?;
|
||||
self.payload.term_stream.term_queue.push_back(term);
|
||||
|
||||
@@ -77,6 +77,12 @@ impl ValidType {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub(crate) enum ResourceError {
|
||||
FiniteMemory(HeapCellValue),
|
||||
OutOfFiles
|
||||
}
|
||||
|
||||
pub(crate) trait TypeError {
|
||||
fn type_error(self, machine_st: &mut MachineState, valid_type: ValidType) -> MachineError;
|
||||
}
|
||||
@@ -155,6 +161,26 @@ pub(crate) trait PermissionError {
|
||||
) -> MachineError;
|
||||
}
|
||||
|
||||
impl PermissionError for Atom {
|
||||
fn permission_error(
|
||||
self,
|
||||
_machine_st: &mut MachineState,
|
||||
index_atom: Atom,
|
||||
perm: Permission,
|
||||
) -> MachineError {
|
||||
let stub = functor!(
|
||||
atom!("permission_error"),
|
||||
[atom(perm.as_atom()), atom(index_atom), cell(atom_as_cell!(self))]
|
||||
);
|
||||
|
||||
MachineError {
|
||||
stub,
|
||||
location: None,
|
||||
from: ErrorProvenance::Received,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl PermissionError for HeapCellValue {
|
||||
fn permission_error(
|
||||
self,
|
||||
@@ -284,11 +310,21 @@ impl MachineState {
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn resource_error(&mut self, value: HeapCellValue) -> MachineError {
|
||||
let stub = functor!(
|
||||
atom!("resource_error"),
|
||||
[atom(atom!("finite_memory")), cell(value)]
|
||||
);
|
||||
pub(super) fn resource_error(&mut self, err: ResourceError) -> MachineError {
|
||||
let stub = match err {
|
||||
ResourceError::FiniteMemory(size_requested) => {
|
||||
functor!(
|
||||
atom!("resource_error"),
|
||||
[atom(atom!("finite_memory")), cell(size_requested)]
|
||||
)
|
||||
}
|
||||
ResourceError::OutOfFiles => {
|
||||
functor!(
|
||||
atom!("resource_error"),
|
||||
[atom(atom!("file_descriptors"))]
|
||||
)
|
||||
}
|
||||
};
|
||||
|
||||
MachineError {
|
||||
stub,
|
||||
@@ -305,26 +341,6 @@ impl MachineState {
|
||||
culprit.type_error(self, valid_type)
|
||||
}
|
||||
|
||||
pub(super) fn module_resolution_error(
|
||||
&mut self,
|
||||
mod_name: Atom,
|
||||
name: Atom,
|
||||
arity: usize,
|
||||
) -> MachineError {
|
||||
let h = self.heap.len();
|
||||
|
||||
let res_stub = functor!(atom!(":"), [atom(mod_name), atom(name)]);
|
||||
let ind_stub = functor!(atom!("/"), [str(h + 2, 0), fixnum(arity)], [res_stub]);
|
||||
|
||||
let stub = functor!(atom!("evaluation_error"), [str(h, 0)], [ind_stub]);
|
||||
|
||||
MachineError {
|
||||
stub,
|
||||
location: None,
|
||||
from: ErrorProvenance::Constructed,
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn existence_error(&mut self, err: ExistenceError) -> MachineError {
|
||||
match err {
|
||||
ExistenceError::Module(name) => {
|
||||
@@ -339,6 +355,20 @@ impl MachineState {
|
||||
from: ErrorProvenance::Received,
|
||||
}
|
||||
}
|
||||
ExistenceError::QualifiedProcedure { module_name, name, arity } => {
|
||||
let h = self.heap.len();
|
||||
|
||||
let ind_stub = functor!(atom!("/"), [atom(name), fixnum(arity)]);
|
||||
let res_stub = functor!(atom!(":"), [atom(module_name), str(h + 3, 0)], [ind_stub]);
|
||||
|
||||
let stub = functor!(atom!("existence_error"), [atom(atom!("procedure")), str(h, 0)], [res_stub]);
|
||||
|
||||
MachineError {
|
||||
stub,
|
||||
location: None,
|
||||
from: ErrorProvenance::Constructed,
|
||||
}
|
||||
}
|
||||
ExistenceError::Procedure(name, arity) => {
|
||||
let culprit = functor!(atom!("/"), [atom(name), fixnum(arity)]);
|
||||
|
||||
@@ -443,7 +473,6 @@ impl MachineState {
|
||||
pub(super) fn session_error(&mut self, err: SessionError) -> MachineError {
|
||||
match err {
|
||||
SessionError::CannotOverwriteBuiltIn(key) => {
|
||||
// SessionError::CannotOverwriteImport(pred_atom) => {
|
||||
self.permission_error(
|
||||
Permission::Modify,
|
||||
atom!("static_procedure"),
|
||||
@@ -452,10 +481,14 @@ impl MachineState {
|
||||
.collect::<MachineStub>(),
|
||||
)
|
||||
}
|
||||
SessionError::CannotOverwriteBuiltInModule(module) => {
|
||||
self.permission_error(
|
||||
Permission::Modify,
|
||||
atom!("static_module"),
|
||||
module,
|
||||
)
|
||||
}
|
||||
SessionError::ExistenceError(err) => self.existence_error(err),
|
||||
// SessionError::InvalidFileName(filename) => {
|
||||
// Self::existence_error(h, ExistenceError::Module(filename))
|
||||
// }
|
||||
SessionError::ModuleDoesNotContainExport(..) => {
|
||||
let error_atom = atom!("module_does_not_contain_claimed_export");
|
||||
|
||||
@@ -953,6 +986,7 @@ pub enum ExistenceError {
|
||||
Module(Atom),
|
||||
ModuleSource(ModuleSource),
|
||||
Procedure(Atom, usize),
|
||||
QualifiedProcedure { module_name: Atom, name: Atom, arity: usize },
|
||||
SourceSink(HeapCellValue),
|
||||
Stream(HeapCellValue),
|
||||
}
|
||||
@@ -961,6 +995,7 @@ pub enum ExistenceError {
|
||||
pub enum SessionError {
|
||||
CompilationError(CompilationError),
|
||||
CannotOverwriteBuiltIn(PredicateKey),
|
||||
CannotOverwriteBuiltInModule(Atom),
|
||||
ExistenceError(ExistenceError),
|
||||
ModuleDoesNotContainExport(Atom, PredicateKey),
|
||||
ModuleCannotImportSelf(Atom),
|
||||
|
||||
@@ -96,7 +96,7 @@ 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) -> CallResult,
|
||||
pub(crate) increment_call_count_fn: fn(&mut MachineState) -> bool,
|
||||
}
|
||||
|
||||
impl fmt::Debug for MachineState {
|
||||
@@ -412,22 +412,24 @@ impl MachineState {
|
||||
self.fail = false;
|
||||
}
|
||||
|
||||
pub(crate) fn increment_call_count(&mut self) -> CallResult {
|
||||
pub(crate) fn increment_call_count(&mut self) -> bool {
|
||||
if self.cwil.inference_limit_exceeded || self.ball.stub.len() > 0 {
|
||||
return Ok(());
|
||||
return true;
|
||||
}
|
||||
|
||||
if let Some(&(ref limit, bp)) = self.cwil.limits.last() {
|
||||
if let Some(&(ref limit, block)) = self.cwil.limits.last() {
|
||||
if self.cwil.count == *limit {
|
||||
self.cwil.inference_limit_exceeded = true;
|
||||
self.block = block;
|
||||
self.unwind_stack();
|
||||
|
||||
return Err(functor!(atom!("inference_limit_exceeded"), [fixnum(bp)]));
|
||||
return false;
|
||||
} else {
|
||||
self.cwil.count += 1;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
true
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
@@ -588,7 +590,7 @@ impl MachineState {
|
||||
|
||||
let mut singleton_var_set: IndexMap<Ref, bool> = IndexMap::new();
|
||||
|
||||
for cell in stackful_preorder_iter(&mut self.heap, &mut self.stack, heap_loc) {
|
||||
for cell in stackful_preorder_iter::<NonListElider>(&mut self.heap, &mut self.stack, heap_loc) {
|
||||
let cell = unmark_cell_bits!(cell);
|
||||
|
||||
if let Some(var) = cell.as_var() {
|
||||
@@ -953,7 +955,7 @@ impl MachineState {
|
||||
pub(crate) struct CWIL {
|
||||
count: Integer,
|
||||
limits: Vec<(Integer, usize)>,
|
||||
inference_limit_exceeded: bool,
|
||||
pub(crate) inference_limit_exceeded: bool,
|
||||
}
|
||||
|
||||
impl CWIL {
|
||||
@@ -965,22 +967,22 @@ impl CWIL {
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn add_limit(&mut self, limit: usize, b: usize) -> &Integer {
|
||||
pub(crate) fn add_limit(&mut self, limit: usize, block: usize) -> &Integer {
|
||||
let mut limit = Integer::from(limit);
|
||||
limit += &self.count;
|
||||
|
||||
match self.limits.last() {
|
||||
Some((ref inner_limit, _)) if *inner_limit <= limit => {}
|
||||
_ => self.limits.push((limit, b)),
|
||||
_ => self.limits.push((limit, block)),
|
||||
};
|
||||
|
||||
&self.count
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub(crate) fn remove_limit(&mut self, b: usize) -> &Integer {
|
||||
if let Some((_, bp)) = self.limits.last() {
|
||||
if bp == &b {
|
||||
pub(crate) fn remove_limit(&mut self, block: usize) -> &Integer {
|
||||
if let Some((_, bl)) = self.limits.last() {
|
||||
if bl == &block {
|
||||
self.limits.pop();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,7 +16,6 @@ use crate::parser::dashu::{Integer, Rational};
|
||||
use crate::types::*;
|
||||
|
||||
use indexmap::IndexSet;
|
||||
use num_order::NumOrd;
|
||||
|
||||
use std::cmp::Ordering;
|
||||
use std::convert::TryFrom;
|
||||
@@ -61,7 +60,7 @@ impl MachineState {
|
||||
unify_fn: MachineState::unify,
|
||||
bind_fn: MachineState::bind,
|
||||
run_cleaners_fn: |_| false,
|
||||
increment_call_count_fn: |_| Ok(()),
|
||||
increment_call_count_fn: |_| true,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1136,7 +1135,8 @@ impl MachineState {
|
||||
return false;
|
||||
}
|
||||
|
||||
let mut iter = stackful_preorder_iter(&mut self.heap, &mut self.stack, value);
|
||||
let mut iter = stackful_preorder_iter::<NonListElider>
|
||||
(&mut self.heap, &mut self.stack, value);
|
||||
|
||||
while let Some(value) = iter.next() {
|
||||
if value.get_forwarding_bit() {
|
||||
@@ -1183,10 +1183,7 @@ impl MachineState {
|
||||
|
||||
let n = match n {
|
||||
Number::Fixnum(n) => n.get_num() as usize,
|
||||
Number::Integer(n) if (*n).num_ge(&0) && (*n).num_le(&std::usize::MAX) => {
|
||||
let value: usize = (&*n).try_into().unwrap();
|
||||
value
|
||||
},
|
||||
Number::Integer(n) if usize::try_from(&*n).is_ok() => (&*n).try_into().unwrap(),
|
||||
_ => {
|
||||
self.fail = true;
|
||||
return Ok(());
|
||||
@@ -1637,24 +1634,36 @@ impl MachineState {
|
||||
}
|
||||
|
||||
let mut visited = IndexSet::with_hasher(FxBuildHasher::default());
|
||||
let mut iter = stackful_preorder_iter(&mut self.heap, &mut self.stack, value);
|
||||
let mut iter = stackful_preorder_iter::<NonListElider>(&mut self.heap, &mut self.stack, value);
|
||||
let mut stack_len = 0;
|
||||
|
||||
while let Some(value) = iter.next() {
|
||||
let mut value = unmark_cell_bits!(value);
|
||||
let is_var = |heap: &Heap, value: HeapCellValue| -> bool {
|
||||
let value = unmark_cell_bits!(value);
|
||||
|
||||
if value.is_var() {
|
||||
value = heap_bound_store(iter.heap, heap_bound_deref(iter.heap, value));
|
||||
let value = heap_bound_store(heap, heap_bound_deref(heap, value));
|
||||
|
||||
if value.is_var() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if value.is_compound(iter.heap) {
|
||||
false
|
||||
};
|
||||
|
||||
while let Some(value) = iter.next() {
|
||||
if is_var(iter.heap, value) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if value.is_ref() {
|
||||
if visited.contains(&value) {
|
||||
for _ in stack_len..iter.stack_len() {
|
||||
iter.pop_stack();
|
||||
while iter.stack_len() > stack_len {
|
||||
if let Some(value) = iter.pop_stack() {
|
||||
if is_var(iter.heap, value) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
visited.insert(value);
|
||||
@@ -1689,7 +1698,7 @@ impl MachineState {
|
||||
},
|
||||
Ok(Number::Integer(n)) => {
|
||||
let b: u8 = (&*n).try_into().unwrap();
|
||||
|
||||
|
||||
bytes.push(b);
|
||||
}
|
||||
_ => {}
|
||||
|
||||
@@ -60,6 +60,9 @@ use std::sync::atomic::AtomicBool;
|
||||
|
||||
use self::config::MachineConfig;
|
||||
use self::parsed_results::*;
|
||||
use tokio::runtime::Runtime;
|
||||
use rand::rngs::StdRng;
|
||||
use rand::SeedableRng;
|
||||
|
||||
lazy_static! {
|
||||
pub static ref INTERRUPT: AtomicBool = AtomicBool::new(false);
|
||||
@@ -76,6 +79,7 @@ pub struct Machine {
|
||||
pub(super) load_contexts: Vec<LoadContext>,
|
||||
#[cfg(feature = "ffi")]
|
||||
pub(super) foreign_function_table: ForeignFunctionTable,
|
||||
pub(super) rng: StdRng,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
@@ -487,6 +491,7 @@ impl Machine {
|
||||
load_contexts: vec![],
|
||||
#[cfg(feature = "ffi")]
|
||||
foreign_function_table: Default::default(),
|
||||
rng: StdRng::from_entropy(),
|
||||
};
|
||||
|
||||
let mut lib_path = current_dir();
|
||||
@@ -1178,7 +1183,7 @@ impl Machine {
|
||||
let stub = functor_stub(name, arity);
|
||||
let err = self
|
||||
.machine_st
|
||||
.module_resolution_error(module_name, name, arity);
|
||||
.existence_error(ExistenceError::QualifiedProcedure { module_name, name, arity });
|
||||
|
||||
Err(self.machine_st.error_form(err, stub))
|
||||
}
|
||||
@@ -1206,7 +1211,7 @@ impl Machine {
|
||||
let stub = functor_stub(name, arity);
|
||||
let err = self
|
||||
.machine_st
|
||||
.module_resolution_error(module_name, name, arity);
|
||||
.existence_error(ExistenceError::QualifiedProcedure { module_name, name, arity });
|
||||
|
||||
Err(self.machine_st.error_form(err, stub))
|
||||
}
|
||||
|
||||
@@ -58,10 +58,7 @@ fn setup_predicate_indicator(term: &mut Term) -> Result<PredicateKey, Compilatio
|
||||
let name = terms.pop().unwrap();
|
||||
|
||||
let arity = match arity {
|
||||
Term::Literal(_, Literal::Integer(n)) => {
|
||||
let value: usize = (&*n).try_into().unwrap();
|
||||
Some(value)
|
||||
},
|
||||
Term::Literal(_, Literal::Integer(n)) => (&*n).try_into().ok(),
|
||||
Term::Literal(_, Literal::Fixnum(n)) => usize::try_from(n.get_num()).ok(),
|
||||
_ => None,
|
||||
}
|
||||
|
||||
@@ -30,6 +30,9 @@ use std::ptr;
|
||||
#[cfg(feature = "tls")]
|
||||
use native_tls::TlsStream;
|
||||
|
||||
#[cfg(feature = "http")]
|
||||
use warp::hyper;
|
||||
|
||||
#[derive(Debug, BitfieldSpecifier, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
#[bits = 1]
|
||||
pub enum StreamType {
|
||||
@@ -290,9 +293,9 @@ impl Read for HttpReadStream {
|
||||
#[cfg(feature = "http")]
|
||||
pub struct HttpWriteStream {
|
||||
status_code: u16,
|
||||
headers: hyper::HeaderMap,
|
||||
headers: mem::ManuallyDrop<hyper::HeaderMap>,
|
||||
response: TypedArenaPtr<HttpResponse>,
|
||||
buffer: Vec<u8>,
|
||||
buffer: mem::ManuallyDrop<Vec<u8>>,
|
||||
}
|
||||
|
||||
#[cfg(feature = "http")]
|
||||
@@ -312,24 +315,33 @@ impl Write for HttpWriteStream {
|
||||
|
||||
#[inline]
|
||||
fn flush(&mut self) -> std::io::Result<()> {
|
||||
let (ready, response, cvar) = &**self.response;
|
||||
|
||||
let mut ready = ready.lock().unwrap();
|
||||
{
|
||||
let mut response = response.lock().unwrap();
|
||||
|
||||
let bytes = bytes::Bytes::copy_from_slice(&self.buffer);
|
||||
let mut response_ = hyper::Response::builder().status(self.status_code);
|
||||
*response_.headers_mut().unwrap() = self.headers.clone();
|
||||
*response = Some(response_.body(http_body_util::Full::new(bytes)).unwrap());
|
||||
}
|
||||
*ready = true;
|
||||
cvar.notify_one();
|
||||
|
||||
Ok(())
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "http")]
|
||||
impl HttpWriteStream {
|
||||
fn drop(&mut self) {
|
||||
let headers = unsafe { mem::ManuallyDrop::take(&mut self.headers) };
|
||||
let buffer = unsafe { mem::ManuallyDrop::take(&mut self.buffer) };
|
||||
|
||||
let (ready, response, cvar) = &**self.response;
|
||||
|
||||
let mut ready = ready.lock().unwrap();
|
||||
{
|
||||
let mut response = response.lock().unwrap();
|
||||
|
||||
let mut response_ = warp::http::Response::builder()
|
||||
.status(self.status_code);
|
||||
*response_.headers_mut().unwrap() = headers;
|
||||
*response = Some(response_.body(warp::hyper::Body::from(buffer)).unwrap());
|
||||
}
|
||||
*ready = true;
|
||||
cvar.notify_one();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct StandardOutputStream {}
|
||||
|
||||
@@ -1243,15 +1255,15 @@ impl Stream {
|
||||
headers: hyper::HeaderMap,
|
||||
arena: &mut Arena,
|
||||
) -> Self {
|
||||
Stream::HttpWrite(arena_alloc!(
|
||||
StreamLayout::new(CharReader::new(HttpWriteStream {
|
||||
response,
|
||||
status_code,
|
||||
headers,
|
||||
buffer: Vec::new(),
|
||||
})),
|
||||
arena
|
||||
))
|
||||
Stream::HttpWrite(arena_alloc!(
|
||||
StreamLayout::new(CharReader::new(HttpWriteStream {
|
||||
response,
|
||||
status_code,
|
||||
headers: mem::ManuallyDrop::new(headers),
|
||||
buffer: mem::ManuallyDrop::new(Vec::new()),
|
||||
})),
|
||||
arena
|
||||
))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
@@ -1299,7 +1311,8 @@ impl Stream {
|
||||
Ok(())
|
||||
}
|
||||
#[cfg(feature = "http")]
|
||||
Stream::HttpWrite(ref mut http_stream) => {
|
||||
Stream::HttpWrite(ref mut http_stream) => {
|
||||
http_stream.inner_mut().drop();
|
||||
unsafe {
|
||||
http_stream.set_tag(ArenaHeaderTag::Dropped);
|
||||
std::ptr::drop_in_place(&mut http_stream.inner_mut().buffer as *mut _);
|
||||
@@ -1804,7 +1817,7 @@ impl MachineState {
|
||||
) -> Result<Stream, MachineStub> {
|
||||
if file_spec == atom!("") {
|
||||
let stub = functor_stub(atom!("open"), 4);
|
||||
let err = self.domain_error(DomainErrorType::SourceSink, self[temp_v!(1)]);
|
||||
let err = self.domain_error(DomainErrorType::SourceSink, self.registers[1]);
|
||||
|
||||
return Err(self.error_form(err, stub));
|
||||
}
|
||||
@@ -1816,9 +1829,7 @@ impl MachineState {
|
||||
}
|
||||
}
|
||||
|
||||
let mode = MachineState::deref(self, self[temp_v!(2)]);
|
||||
let mode = cell_as_atom!(self.store(mode));
|
||||
|
||||
let mode = cell_as_atom!(self.store(MachineState::deref(self, self.registers[2])));
|
||||
let mut open_options = OpenOptions::new();
|
||||
|
||||
let (is_input_file, in_append_mode) = match mode {
|
||||
@@ -1875,8 +1886,9 @@ impl MachineState {
|
||||
));
|
||||
}
|
||||
_ => {
|
||||
// assume the OS is out of file descriptors.
|
||||
let stub = functor_stub(atom!("open"), 4);
|
||||
let err = self.syntax_error(ParserError::IO(err));
|
||||
let err = self.resource_error(ResourceError::OutOfFiles);
|
||||
|
||||
return Err(self.error_form(err, stub));
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@ use crate::forms::*;
|
||||
use crate::heap_iter::*;
|
||||
use crate::heap_print::*;
|
||||
#[cfg(feature = "http")]
|
||||
use crate::http::{HttpListener, HttpResponse, HttpService};
|
||||
use crate::http::{HttpRequestData, HttpListener, HttpResponse, HttpRequest};
|
||||
use crate::instructions::*;
|
||||
use crate::machine;
|
||||
use crate::machine::code_walker::*;
|
||||
@@ -42,17 +42,16 @@ use indexmap::IndexSet;
|
||||
|
||||
pub(crate) use ref_thread_local::RefThreadLocal;
|
||||
|
||||
use std::borrow::BorrowMut;
|
||||
use std::cell::Cell;
|
||||
use std::cmp::Ordering;
|
||||
use std::collections::BTreeSet;
|
||||
use std::collections::{BTreeSet};
|
||||
use std::convert::TryFrom;
|
||||
use std::env;
|
||||
#[cfg(feature = "ffi")]
|
||||
use std::ffi::CString;
|
||||
use std::fs;
|
||||
use std::hash::{BuildHasher, BuildHasherDefault};
|
||||
use std::io::{ErrorKind, Read, Write};
|
||||
use std::io::{ErrorKind, Read, BufRead, Write};
|
||||
use std::iter::{once, FromIterator};
|
||||
use std::mem;
|
||||
use std::net::{SocketAddr, TcpListener, TcpStream, ToSocketAddrs};
|
||||
@@ -60,6 +59,7 @@ use std::num::NonZeroU32;
|
||||
use std::ops::Sub;
|
||||
use std::process;
|
||||
use std::str::FromStr;
|
||||
use std::sync::{Mutex, Arc, Condvar};
|
||||
|
||||
use chrono::{offset::Local, DateTime};
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
@@ -77,7 +77,7 @@ use ring::{digest, hkdf, pbkdf2};
|
||||
|
||||
#[cfg(feature = "crypto-full")]
|
||||
use ring::{
|
||||
aead,
|
||||
aead,
|
||||
signature::{self, KeyPair},
|
||||
};
|
||||
use ripemd160::{Digest, Ripemd160};
|
||||
@@ -92,17 +92,16 @@ use base64;
|
||||
use roxmltree;
|
||||
use select;
|
||||
|
||||
use bytes::Buf;
|
||||
use http_body_util::BodyExt;
|
||||
#[cfg(feature = "http")]
|
||||
use hyper::header::{HeaderName, HeaderValue};
|
||||
use warp::hyper::header::{HeaderValue, HeaderName};
|
||||
#[cfg(feature = "http")]
|
||||
use hyper::server::conn::http1;
|
||||
use warp::hyper::{HeaderMap, Method};
|
||||
#[cfg(feature = "http")]
|
||||
use hyper::{HeaderMap, Method};
|
||||
use warp::{Buf, Filter};
|
||||
#[cfg(feature = "http")]
|
||||
use reqwest::Url;
|
||||
use hyper_util::rt::TokioIo;
|
||||
//use hyper_util::rt::TokioIo;
|
||||
use futures::future;
|
||||
|
||||
#[cfg(feature = "repl")]
|
||||
pub(crate) fn get_key() -> KeyEvent {
|
||||
@@ -182,12 +181,6 @@ impl BrentAlgState {
|
||||
}
|
||||
|
||||
pub fn to_result(mut self, heap: &[HeapCellValue]) -> CycleSearchResult {
|
||||
/*
|
||||
if let Some(var) = heap[self.hare].as_var() {
|
||||
return CycleSearchResult::PartialList(self.num_steps(), var);
|
||||
}
|
||||
*/
|
||||
|
||||
loop {
|
||||
read_heap_cell!(heap[self.hare],
|
||||
(HeapCellValueTag::PStrOffset) => {
|
||||
@@ -250,7 +243,7 @@ impl BrentAlgState {
|
||||
let cstr = PartialString::from(cstr_atom);
|
||||
let num_chars = cstr.as_str_from(offset).chars().count();
|
||||
|
||||
if self.max_steps == -1 || self.num_steps() + num_chars < self.max_steps as usize {
|
||||
if self.max_steps == -1 || self.num_steps() + num_chars <= self.max_steps as usize {
|
||||
self.pstr_chars += num_chars;
|
||||
Some(CycleSearchResult::ProperList(self.num_steps()))
|
||||
} else {
|
||||
@@ -263,7 +256,7 @@ impl BrentAlgState {
|
||||
let pstr = PartialString::from(pstr_atom);
|
||||
let num_chars = pstr.as_str_from(offset).chars().count();
|
||||
|
||||
if self.max_steps == -1 || self.num_steps() + num_chars < self.max_steps as usize {
|
||||
if self.max_steps == -1 || self.num_steps() + num_chars <= self.max_steps as usize {
|
||||
self.pstr_chars += num_chars - 1;
|
||||
self.step(h+1)
|
||||
} else {
|
||||
@@ -591,7 +584,7 @@ impl MachineState {
|
||||
seen_set: &mut IndexSet<HeapCellValue, S>,
|
||||
value: HeapCellValue,
|
||||
) {
|
||||
let mut iter = stackful_preorder_iter(&mut self.heap, &mut self.stack, value);
|
||||
let mut iter = stackful_preorder_iter::<NonListElider>(&mut self.heap, &mut self.stack, value);
|
||||
|
||||
while let Some(value) = iter.next() {
|
||||
let value = unmark_cell_bits!(value);
|
||||
@@ -801,7 +794,7 @@ impl MachineState {
|
||||
let mut seen_set = IndexSet::new();
|
||||
|
||||
{
|
||||
let mut iter = stackful_post_order_iter(&mut self.heap, &mut self.stack, term);
|
||||
let mut iter = stackful_post_order_iter::<NonListElider>(&mut self.heap, &mut self.stack, term);
|
||||
|
||||
while let Some(value) = iter.next() {
|
||||
if iter.parent_stack_len() >= max_depth {
|
||||
@@ -1419,7 +1412,6 @@ impl Machine {
|
||||
is_simple_goal: bool,
|
||||
goal: HeapCellValue,
|
||||
key: PredicateKey,
|
||||
expanded_vars: IndexSet<HeapCellValue, BuildHasherDefault<FxHasher>>,
|
||||
supp_vars: IndexSet<HeapCellValue, BuildHasherDefault<FxHasher>>,
|
||||
}
|
||||
|
||||
@@ -1444,7 +1436,7 @@ impl Machine {
|
||||
// insertion as well as the previous
|
||||
// supp_vars.len() argument's variables being
|
||||
// disjoint from them. if they are not, the
|
||||
// expanded goal are not simple.
|
||||
// expanded goal is not simple.
|
||||
|
||||
let post_supp_args = self.machine_st.heap[s+arity-supp_vars.len()+1 .. s+arity+1]
|
||||
.iter()
|
||||
@@ -1490,7 +1482,6 @@ impl Machine {
|
||||
is_simple_goal,
|
||||
goal,
|
||||
key: (name, arity),
|
||||
expanded_vars,
|
||||
supp_vars
|
||||
}
|
||||
}
|
||||
@@ -1504,7 +1495,6 @@ impl Machine {
|
||||
is_simple_goal: true,
|
||||
goal: str_loc_as_cell!(h),
|
||||
key: (name, 0),
|
||||
expanded_vars: IndexSet::with_hasher(FxBuildHasher::default()),
|
||||
supp_vars,
|
||||
}
|
||||
}
|
||||
@@ -1518,7 +1508,6 @@ impl Machine {
|
||||
is_simple_goal: true,
|
||||
goal: str_loc_as_cell!(h),
|
||||
key: (name, 0),
|
||||
expanded_vars: IndexSet::with_hasher(FxBuildHasher::default()),
|
||||
supp_vars,
|
||||
}
|
||||
}
|
||||
@@ -1540,9 +1529,12 @@ impl Machine {
|
||||
.push(untyped_arena_ptr_as_cell!(UntypedArenaPtr::from(idx)));
|
||||
result.goal
|
||||
} else {
|
||||
let mut unexpanded_vars = IndexSet::with_hasher(FxBuildHasher::default());
|
||||
self.machine_st.variable_set(&mut unexpanded_vars, self.machine_st.registers[5]);
|
||||
|
||||
// all supp_vars must appear later!
|
||||
let vars = IndexSet::<HeapCellValue, BuildHasherDefault<FxHasher>>::from_iter(
|
||||
result.expanded_vars.difference(&result.supp_vars).cloned(),
|
||||
unexpanded_vars.difference(&result.supp_vars).cloned(),
|
||||
);
|
||||
|
||||
let vars: Vec<_> = vars
|
||||
@@ -1564,7 +1556,7 @@ impl Machine {
|
||||
|
||||
self.machine_st.heap.push(atom_as_cell!(atom!("$aux"), 0));
|
||||
|
||||
for value in result.expanded_vars.difference(&result.supp_vars).cloned() {
|
||||
for value in unexpanded_vars.difference(&result.supp_vars).cloned() {
|
||||
self.machine_st.heap.push(value);
|
||||
}
|
||||
|
||||
@@ -3265,7 +3257,7 @@ impl Machine {
|
||||
match Number::try_from(addr) {
|
||||
Ok(Number::Integer(n)) => {
|
||||
let n: u8 = (&*n).try_into().unwrap();
|
||||
|
||||
|
||||
match n {
|
||||
nb => {
|
||||
match stream.write(&mut [nb]) {
|
||||
@@ -3916,6 +3908,11 @@ impl Machine {
|
||||
}
|
||||
);
|
||||
|
||||
if self.indices.builtin_property((name, arity)) {
|
||||
self.machine_st.fail = true;
|
||||
return;
|
||||
}
|
||||
|
||||
self.machine_st.fail = self
|
||||
.indices
|
||||
.get_predicate_code_index(name, arity, module_name)
|
||||
@@ -3995,6 +3992,10 @@ impl Machine {
|
||||
};
|
||||
|
||||
for (name, arity) in code_dir.keys() {
|
||||
if self.indices.builtin_property((*name, *arity)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if name_match(pred_atom, *name) && arity_match(pred_arity, *arity) {
|
||||
self.machine_st.heap.extend(functor!(
|
||||
atom!("/"),
|
||||
@@ -4217,25 +4218,7 @@ impl Machine {
|
||||
|
||||
#[inline(always)]
|
||||
pub(crate) fn maybe(&mut self) {
|
||||
fn generate_random_bits(num_bits: usize) -> u64 {
|
||||
let mut rng = rand::thread_rng();
|
||||
let rand = rng.borrow_mut();
|
||||
let mut random_bits: u64 = 0;
|
||||
|
||||
for _ in 0..num_bits {
|
||||
random_bits <<= 1;
|
||||
|
||||
if rand.gen_bool(0.5) {
|
||||
random_bits |= 1;
|
||||
}
|
||||
}
|
||||
|
||||
random_bits
|
||||
}
|
||||
|
||||
let result = { generate_random_bits(1) == 0 };
|
||||
|
||||
self.machine_st.fail = result;
|
||||
self.machine_st.fail = self.rng.gen();
|
||||
}
|
||||
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
@@ -4264,7 +4247,7 @@ impl Machine {
|
||||
Ok(Number::Integer(n)) => match (&*n).try_into() as Result<usize, _> {
|
||||
Ok(n) => n,
|
||||
Err(_) => {
|
||||
let err = self.machine_st.resource_error(len);
|
||||
let err = self.machine_st.resource_error(ResourceError::FiniteMemory(len));
|
||||
return Err(self.machine_st.error_form(err, stub_gen()));
|
||||
}
|
||||
},
|
||||
@@ -4429,64 +4412,128 @@ impl Machine {
|
||||
#[inline(always)]
|
||||
pub(crate) fn http_listen(&mut self) -> CallResult {
|
||||
let address_sink = self.deref_register(1);
|
||||
if let Some(address_str) = self.machine_st.value_to_str_like(address_sink) {
|
||||
let address_string = address_str.as_str();
|
||||
let addr: SocketAddr = match address_string
|
||||
.to_socket_addrs()
|
||||
.ok()
|
||||
.and_then(|mut s| s.next())
|
||||
{
|
||||
Some(addr) => addr,
|
||||
_ => {
|
||||
self.machine_st.fail = true;
|
||||
return Ok(());
|
||||
}
|
||||
};
|
||||
let tls_key = self.deref_register(3);
|
||||
let tls_cert = self.deref_register(4);
|
||||
let content_length_limit = self.deref_register(5);
|
||||
const CONTENT_LENGTH_LIMIT_DEFAULT: u64 = 32768;
|
||||
let content_length_limit = match Number::try_from(content_length_limit) {
|
||||
Ok(Number::Fixnum(n)) => if n.get_num() >= 0 {
|
||||
n.get_num() as u64
|
||||
} else {
|
||||
CONTENT_LENGTH_LIMIT_DEFAULT
|
||||
},
|
||||
Ok(Number::Integer(n)) => {
|
||||
let n: Result<u64, _> = (&*n).try_into();
|
||||
match n {
|
||||
Ok(u) => u,
|
||||
Err(_) => CONTENT_LENGTH_LIMIT_DEFAULT,
|
||||
}
|
||||
}
|
||||
_ => CONTENT_LENGTH_LIMIT_DEFAULT,
|
||||
};
|
||||
|
||||
let (tx, rx) = std::sync::mpsc::sync_channel(1024);
|
||||
let ssl_server: Option<(String,String)> = {
|
||||
match self.machine_st.value_to_str_like(tls_key) {
|
||||
Some(key) => {
|
||||
match self.machine_st.value_to_str_like(tls_cert) {
|
||||
Some(cert) => {
|
||||
let key_str = key.as_str();
|
||||
let cert_str = cert.as_str();
|
||||
|
||||
if key_str.is_empty() || cert_str.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some((key_str.to_string(), cert_str.to_string()))
|
||||
}
|
||||
}
|
||||
None => None
|
||||
}
|
||||
}
|
||||
None => None
|
||||
}
|
||||
};
|
||||
|
||||
let runtime = tokio::runtime::Handle::current();
|
||||
let _guard = runtime.enter();
|
||||
if let Some(address_str) = self.machine_st.value_to_str_like(address_sink) {
|
||||
let address_string = address_str.as_str();
|
||||
let addr: SocketAddr = match address_string.to_socket_addrs().ok().and_then(|mut s| s.next()) {
|
||||
Some(addr) => addr,
|
||||
_ => {
|
||||
self.machine_st.fail = true;
|
||||
return Ok(());
|
||||
}
|
||||
};
|
||||
|
||||
let listener = match runtime
|
||||
.block_on(async { tokio::net::TcpListener::bind(addr).await })
|
||||
{
|
||||
Ok(listener) => listener,
|
||||
Err(_) => {
|
||||
return Err(self.machine_st.open_permission_error(
|
||||
address_sink,
|
||||
atom!("http_listen"),
|
||||
2,
|
||||
));
|
||||
}
|
||||
};
|
||||
let (tx, rx) = std::sync::mpsc::sync_channel(1024);
|
||||
|
||||
runtime.spawn(async move {
|
||||
loop {
|
||||
let tx = tx.clone();
|
||||
let (stream, _) = listener.accept().await.unwrap();
|
||||
|
||||
tokio::task::spawn(async move {
|
||||
let io = TokioIo::new(stream);
|
||||
|
||||
if let Err(err) = http1::Builder::new()
|
||||
.serve_connection(io, HttpService {tx})
|
||||
.await
|
||||
{
|
||||
eprintln!("Error serving connection: {:?}", err);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
let http_listener = HttpListener { incoming: rx };
|
||||
let http_listener = arena_alloc!(http_listener, &mut self.machine_st.arena);
|
||||
let runtime = tokio::runtime::Handle::current();
|
||||
let _guard = runtime.enter();
|
||||
|
||||
let addr = self.deref_register(2);
|
||||
self.machine_st.bind(
|
||||
addr.as_var().unwrap(),
|
||||
typed_arena_ptr_as_cell!(http_listener),
|
||||
);
|
||||
fn get_reader(body: impl Buf + Send + 'static) -> Box<dyn BufRead + Send> {
|
||||
Box::new(body.reader())
|
||||
}
|
||||
|
||||
let serve = warp::body::aggregate()
|
||||
.and(warp::header::optional::<u64>(warp::http::header::CONTENT_LENGTH.as_str()))
|
||||
.and(warp::method())
|
||||
.and(warp::header::headers_cloned())
|
||||
.and(warp::path::full())
|
||||
.and(warp::query::raw().or_else(|_| future::ready(Ok::<(String,), warp::Rejection>(("".to_string(),)))))
|
||||
.map(move |body, content_length, method, headers: warp::http::HeaderMap, path: warp::filters::path::FullPath, query| {
|
||||
if let Some(content_length) = content_length {
|
||||
if content_length > content_length_limit {
|
||||
return warp::http::Response::builder()
|
||||
.status(413)
|
||||
.body(warp::hyper::Body::empty())
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
let http_request_data = HttpRequestData {
|
||||
method,
|
||||
headers,
|
||||
path: path.as_str().to_string(),
|
||||
query,
|
||||
body: get_reader(body),
|
||||
};
|
||||
let response = Arc::new((Mutex::new(false), Mutex::new(None), Condvar::new()));
|
||||
let http_request = HttpRequest { request_data: http_request_data, response: Arc::clone(&response) };
|
||||
// we send the request to http_accept
|
||||
tx.send(http_request).unwrap();
|
||||
|
||||
// we wait for the Response info from Prolog
|
||||
{
|
||||
let (ready, _response, cvar) = &*response;
|
||||
let mut ready = ready.lock().unwrap();
|
||||
while !*ready {
|
||||
ready = cvar.wait(ready).unwrap();
|
||||
}
|
||||
}
|
||||
{
|
||||
let (_, response, _) = &*response;
|
||||
let response = response.lock().unwrap().take();
|
||||
response.expect("Data race error in HTTP server")
|
||||
}
|
||||
});
|
||||
|
||||
runtime.spawn(async move {
|
||||
match ssl_server {
|
||||
Some((key, cert)) => {
|
||||
warp::serve(serve).tls().key(key).cert(cert).run(addr).await
|
||||
}
|
||||
None => {
|
||||
warp::serve(serve).run(addr).await
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
let http_listener = HttpListener { incoming: rx };
|
||||
let http_listener = arena_alloc!(http_listener, &mut self.machine_st.arena);
|
||||
|
||||
let addr = self.deref_register(2);
|
||||
self.machine_st.bind(
|
||||
addr.as_var().unwrap(),
|
||||
typed_arena_ptr_as_cell!(http_listener),
|
||||
);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
@@ -4494,75 +4541,94 @@ impl Machine {
|
||||
#[cfg(feature = "http")]
|
||||
#[inline(always)]
|
||||
pub(crate) fn http_accept(&mut self) -> CallResult {
|
||||
let culprit = self.deref_register(1);
|
||||
let method = self.deref_register(2);
|
||||
let path = self.deref_register(3);
|
||||
let query = self.deref_register(5);
|
||||
let stream_addr = self.deref_register(6);
|
||||
let handle_addr = self.deref_register(7);
|
||||
read_heap_cell!(culprit,
|
||||
(HeapCellValueTag::Cons, cons_ptr) => {
|
||||
match_untyped_arena_ptr!(cons_ptr,
|
||||
(ArenaHeaderTag::HttpListener, http_listener) => {
|
||||
match http_listener.incoming.recv() {
|
||||
Ok(request) => {
|
||||
let method_atom = match *request.request.method() {
|
||||
Method::GET => atom!("get"),
|
||||
Method::POST => atom!("post"),
|
||||
Method::PUT => atom!("put"),
|
||||
Method::DELETE => atom!("delete"),
|
||||
Method::PATCH => atom!("patch"),
|
||||
Method::HEAD => atom!("head"),
|
||||
_ => unreachable!(),
|
||||
};
|
||||
let path_atom = AtomTable::build_with(&self.machine_st.atom_tbl, request.request.uri().path());
|
||||
let path_cell = atom_as_cstr_cell!(path_atom);
|
||||
let headers: Vec<HeapCellValue> = request.request.headers().iter().map(|(header_name, header_value)| {
|
||||
let h = self.machine_st.heap.len();
|
||||
let culprit = self.deref_register(1);
|
||||
let method = self.deref_register(2);
|
||||
let path = self.deref_register(3);
|
||||
let query = self.deref_register(5);
|
||||
let stream_addr = self.deref_register(6);
|
||||
let handle_addr = self.deref_register(7);
|
||||
read_heap_cell!(culprit,
|
||||
(HeapCellValueTag::Cons, cons_ptr) => {
|
||||
match_untyped_arena_ptr!(cons_ptr,
|
||||
(ArenaHeaderTag::HttpListener, http_listener) => {
|
||||
loop {
|
||||
match http_listener.incoming.recv_timeout(std::time::Duration::from_millis(200)) {
|
||||
Ok(request) => {
|
||||
let method_atom = match request.request_data.method {
|
||||
Method::GET => atom!("get"),
|
||||
Method::POST => atom!("post"),
|
||||
Method::PUT => atom!("put"),
|
||||
Method::DELETE => atom!("delete"),
|
||||
Method::PATCH => atom!("patch"),
|
||||
Method::HEAD => atom!("head"),
|
||||
Method::OPTIONS => atom!("options"),
|
||||
Method::TRACE => atom!("trace"),
|
||||
Method::CONNECT => atom!("connect"),
|
||||
_ => atom!("unsupported_extension"),
|
||||
};
|
||||
let path_atom = AtomTable::build_with(&self.machine_st.atom_tbl, &request.request_data.path);
|
||||
let path_cell = atom_as_cstr_cell!(path_atom);
|
||||
let headers: Vec<HeapCellValue> = request.request_data.headers.iter().map(|(header_name, header_value)| {
|
||||
let h = self.machine_st.heap.len();
|
||||
let header_term = functor!(AtomTable::build_with(&self.machine_st.atom_tbl, header_name.as_str()), [cell(string_as_cstr_cell!(AtomTable::build_with(&self.machine_st.atom_tbl, header_value.to_str().unwrap())))]);
|
||||
|
||||
let header_term = functor!(
|
||||
AtomTable::build_with(&self.machine_st.atom_tbl, header_name.as_str()),
|
||||
[cell(string_as_cstr_cell!(AtomTable::build_with(&self.machine_st.atom_tbl, header_value.to_str().unwrap())))]
|
||||
);
|
||||
self.machine_st.heap.extend(header_term.into_iter());
|
||||
str_loc_as_cell!(h)
|
||||
}).collect();
|
||||
|
||||
self.machine_st.heap.extend(header_term.into_iter());
|
||||
str_loc_as_cell!(h)
|
||||
}).collect();
|
||||
let headers_list = iter_to_heap_list(&mut self.machine_st.heap, headers.into_iter());
|
||||
|
||||
let headers_list = iter_to_heap_list(&mut self.machine_st.heap, headers.into_iter());
|
||||
let query_str = request.request_data.query;
|
||||
let query_atom = AtomTable::build_with(&self.machine_st.atom_tbl, &query_str);
|
||||
let query_cell = string_as_cstr_cell!(query_atom);
|
||||
|
||||
let query_str = request.request.uri().query().unwrap_or("");
|
||||
let query_atom = AtomTable::build_with(&self.machine_st.atom_tbl, query_str);
|
||||
let query_cell = string_as_cstr_cell!(query_atom);
|
||||
let mut stream = Stream::from_http_stream(
|
||||
path_atom,
|
||||
request.request_data.body,
|
||||
&mut self.machine_st.arena
|
||||
);
|
||||
*stream.options_mut() = StreamOptions::default();
|
||||
stream.options_mut().set_stream_type(StreamType::Binary);
|
||||
self.indices.streams.insert(stream);
|
||||
let stream = stream_as_cell!(stream);
|
||||
|
||||
let hyper_req = request.request;
|
||||
let runtime = tokio::runtime::Handle::current();
|
||||
let buf = runtime.block_on(async {hyper_req.collect().await.unwrap().aggregate()});
|
||||
let reader = buf.reader();
|
||||
let handle = arena_alloc!(request.response, &mut self.machine_st.arena);
|
||||
|
||||
let mut stream = Stream::from_http_stream(
|
||||
path_atom,
|
||||
Box::new(reader),
|
||||
&mut self.machine_st.arena
|
||||
);
|
||||
*stream.options_mut() = StreamOptions::default();
|
||||
stream.options_mut().set_stream_type(StreamType::Binary);
|
||||
self.indices.streams.insert(stream);
|
||||
let stream = stream_as_cell!(stream);
|
||||
self.machine_st.bind(method.as_var().unwrap(), atom_as_cell!(method_atom));
|
||||
self.machine_st.bind(path.as_var().unwrap(), path_cell);
|
||||
unify!(self.machine_st, heap_loc_as_cell!(headers_list), self.machine_st.registers[4]);
|
||||
self.machine_st.bind(query.as_var().unwrap(), query_cell);
|
||||
self.machine_st.bind(stream_addr.as_var().unwrap(), stream);
|
||||
self.machine_st.bind(handle_addr.as_var().unwrap(), typed_arena_ptr_as_cell!(handle));
|
||||
break
|
||||
}
|
||||
Err(std::sync::mpsc::RecvTimeoutError::Timeout) => {
|
||||
let interrupted = machine::INTERRUPT.load(std::sync::atomic::Ordering::Relaxed);
|
||||
|
||||
let handle = arena_alloc!(request.response, &mut self.machine_st.arena);
|
||||
match machine::INTERRUPT.compare_exchange(
|
||||
interrupted,
|
||||
false,
|
||||
std::sync::atomic::Ordering::Relaxed,
|
||||
std::sync::atomic::Ordering::Relaxed,
|
||||
) {
|
||||
Ok(interruption) => {
|
||||
if interruption {
|
||||
self.machine_st.throw_interrupt_exception();
|
||||
self.machine_st.backtrack();
|
||||
let old_runtime = std::mem::replace(&mut self.runtime, tokio::runtime::Runtime::new().unwrap());
|
||||
old_runtime.shutdown_background();
|
||||
break
|
||||
}
|
||||
}
|
||||
Err(_) => unreachable!(),
|
||||
}
|
||||
|
||||
self.machine_st.bind(method.as_var().unwrap(), atom_as_cell!(method_atom));
|
||||
self.machine_st.bind(path.as_var().unwrap(), path_cell);
|
||||
unify!(self.machine_st, heap_loc_as_cell!(headers_list), self.machine_st.registers[4]);
|
||||
self.machine_st.bind(query.as_var().unwrap(), query_cell);
|
||||
self.machine_st.bind(stream_addr.as_var().unwrap(), stream);
|
||||
self.machine_st.bind(handle_addr.as_var().unwrap(), typed_arena_ptr_as_cell!(handle));
|
||||
}
|
||||
Err(_) => {
|
||||
self.machine_st.fail = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
Err(_) => {
|
||||
self.machine_st.fail = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
unreachable!();
|
||||
@@ -4585,7 +4651,7 @@ impl Machine {
|
||||
Ok(Number::Fixnum(n)) => n.get_num() as u16,
|
||||
Ok(Number::Integer(n)) => {
|
||||
let n: Result<u16, _> = (&*n).try_into();
|
||||
|
||||
|
||||
if let Ok(value) = n {
|
||||
value
|
||||
} else {
|
||||
@@ -5597,7 +5663,9 @@ impl Machine {
|
||||
}
|
||||
#[inline(always)]
|
||||
pub(crate) fn redo_attr_var_binding(&mut self) {
|
||||
let var = self.deref_register(1);
|
||||
// registers[1] MUST NOT be dereferenced here. the original
|
||||
// AttrVar binding site must be preserved.
|
||||
let var = self.machine_st.registers[1];
|
||||
let value = self.deref_register(2);
|
||||
|
||||
debug_assert_eq!(HeapCellValueTag::AttrVar, var.get_tag());
|
||||
@@ -5631,7 +5699,7 @@ 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 = |_| Ok(());
|
||||
self.machine_st.increment_call_count_fn = |_| true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5640,11 +5708,10 @@ impl Machine {
|
||||
let a1 = self.deref_register(1);
|
||||
let a2 = self.deref_register(2);
|
||||
|
||||
let bp = cell_as_fixnum!(a1).get_num() as usize;
|
||||
|
||||
let count = self.machine_st.cwil.remove_limit(bp).clone();
|
||||
|
||||
let block = cell_as_fixnum!(a1).get_num() as usize;
|
||||
let count = self.machine_st.cwil.remove_limit(block).clone();
|
||||
let result = count.clone().try_into();
|
||||
|
||||
if let Ok(value) = result{
|
||||
self.machine_st.unify_fixnum(Fixnum::build_with(value), a2);
|
||||
} else {
|
||||
@@ -5811,6 +5878,11 @@ impl Machine {
|
||||
}
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub(crate) fn inference_limit_exceeded(&mut self) {
|
||||
self.machine_st.fail = !self.machine_st.cwil.inference_limit_exceeded;
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub(crate) fn clean_up_block(&mut self) {
|
||||
let nb = self.deref_register(1);
|
||||
@@ -6191,16 +6263,19 @@ impl Machine {
|
||||
match Number::try_from(seed) {
|
||||
Ok(Number::Fixnum(n)) => {
|
||||
let n: u64 = Integer::from(n).try_into().unwrap();
|
||||
let _: StdRng = SeedableRng::seed_from_u64(n);
|
||||
let rng: StdRng = SeedableRng::seed_from_u64(n);
|
||||
self.rng = rng;
|
||||
},
|
||||
Ok(Number::Integer(n)) => {
|
||||
let n: u64 = (&*n).try_into().unwrap();
|
||||
let _: StdRng = SeedableRng::seed_from_u64(n);
|
||||
let rng: StdRng = SeedableRng::seed_from_u64(n);
|
||||
self.rng = rng;
|
||||
},
|
||||
Ok(Number::Rational(n)) => {
|
||||
if n.denominator() == &UBig::from(1 as u32) {
|
||||
let n: u64 = n.numerator().try_into().unwrap();
|
||||
let _: StdRng = SeedableRng::seed_from_u64(n);
|
||||
let rng: StdRng = SeedableRng::seed_from_u64(n);
|
||||
self.rng = rng;
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
@@ -7330,7 +7405,7 @@ impl Machine {
|
||||
let iterations = match Number::try_from(iterations) {
|
||||
Ok(Number::Fixnum(n)) => u64::try_from(n.get_num()).unwrap(),
|
||||
Ok(Number::Integer(n)) => {
|
||||
let n: Result<u64, _> = (&*n).try_into();
|
||||
let n: Result<u64, _> = (&*n).try_into();
|
||||
match n {
|
||||
Ok(i) => i,
|
||||
_ => {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use crate::arena::*;
|
||||
use crate::forms::*;
|
||||
use crate::heap_iter::stackful_preorder_iter;
|
||||
use crate::heap_iter::{NonListElider, stackful_preorder_iter};
|
||||
use crate::machine::machine_state::*;
|
||||
use crate::machine::partial_string::*;
|
||||
use crate::machine::*;
|
||||
@@ -717,7 +717,7 @@ fn bind_with_occurs_check<U: Unifier>(unifier: &mut U, r: Ref, value: HeapCellVa
|
||||
if !value.is_constant() {
|
||||
let machine_st: &mut MachineState = unifier.deref_mut();
|
||||
|
||||
for cell in stackful_preorder_iter(&mut machine_st.heap, &mut machine_st.stack, value) {
|
||||
for cell in stackful_preorder_iter::<NonListElider>(&mut machine_st.heap, &mut machine_st.stack, value) {
|
||||
let cell = unmark_cell_bits!(cell);
|
||||
|
||||
if let Some(inner_r) = cell.as_var() {
|
||||
|
||||
Reference in New Issue
Block a user