use fixnums in place of bignums where possible
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -6,6 +6,8 @@ use crate::prolog::machine::compile::*;
|
||||
use crate::prolog::machine::machine_errors::*;
|
||||
use crate::prolog::machine::streams::*;
|
||||
|
||||
use std::convert::TryFrom;
|
||||
|
||||
impl Machine {
|
||||
pub(super) fn atom_tbl_of(&self, name: &ClauseName) -> TabledData<Atom> {
|
||||
match name {
|
||||
@@ -52,10 +54,16 @@ impl Machine {
|
||||
|
||||
let arity = match self.machine_st.store(self.machine_st.deref(arity)) {
|
||||
Addr::Con(h) => {
|
||||
if let HeapCellValue::Integer(ref arity) = &self.machine_st.heap[h] {
|
||||
arity.to_usize().unwrap()
|
||||
} else {
|
||||
unreachable!()
|
||||
match &self.machine_st.heap[h] {
|
||||
HeapCellValue::Integer(ref arity) => {
|
||||
arity.to_usize().unwrap()
|
||||
}
|
||||
HeapCellValue::Addr(Addr::Fixnum(arity)) => {
|
||||
usize::try_from(*arity).unwrap()
|
||||
}
|
||||
_ => {
|
||||
unreachable!()
|
||||
}
|
||||
}
|
||||
}
|
||||
Addr::Usize(n) => {
|
||||
@@ -102,12 +110,12 @@ impl Machine {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fn abolish_dynamic_clause(&mut self, name: RegType, arity: RegType) {
|
||||
let (name, arity) = self.get_predicate_key(name, arity);
|
||||
|
||||
self.make_undefined(name.clone(), arity);
|
||||
|
||||
|
||||
self.indices.remove_code_index((name.clone(), arity));
|
||||
self.indices.remove_clause_subsection(name.owning_module(), name, arity);
|
||||
}
|
||||
@@ -155,7 +163,7 @@ impl Machine {
|
||||
name,
|
||||
arity,
|
||||
);
|
||||
|
||||
|
||||
self.machine_st = machine_st;
|
||||
|
||||
if let EvalSession::Error(err) = result {
|
||||
@@ -239,11 +247,17 @@ impl Machine {
|
||||
let index = self.machine_st[temp_v!(3)].clone();
|
||||
let index = match self.machine_st.store(self.machine_st.deref(index)) {
|
||||
Addr::Con(h) =>
|
||||
if let HeapCellValue::Integer(ref n) = &self.machine_st.heap[h] {
|
||||
n.to_usize().unwrap()
|
||||
} else {
|
||||
unreachable!()
|
||||
},
|
||||
match &self.machine_st.heap[h] {
|
||||
HeapCellValue::Integer(ref arity) => {
|
||||
arity.to_usize().unwrap()
|
||||
}
|
||||
HeapCellValue::Addr(Addr::Fixnum(arity)) => {
|
||||
usize::try_from(*arity).unwrap()
|
||||
}
|
||||
_ => {
|
||||
unreachable!()
|
||||
}
|
||||
}
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
@@ -260,7 +274,7 @@ impl Machine {
|
||||
if addrs.is_empty() {
|
||||
self.make_undefined(name.clone(), arity);
|
||||
}
|
||||
|
||||
|
||||
self.print_new_dynamic_clause(addrs, name.clone(), arity)
|
||||
}
|
||||
Err(err) => {
|
||||
@@ -280,12 +294,19 @@ impl Machine {
|
||||
fn retract_from_dynamic_predicate(&mut self) {
|
||||
let index = self.machine_st[temp_v!(3)].clone();
|
||||
let index = match self.machine_st.store(self.machine_st.deref(index)) {
|
||||
Addr::Con(h) =>
|
||||
if let HeapCellValue::Integer(n) = &self.machine_st.heap[h] {
|
||||
n.to_usize().unwrap()
|
||||
} else {
|
||||
unreachable!()
|
||||
},
|
||||
Addr::Con(h) => {
|
||||
match &self.machine_st.heap[h] {
|
||||
HeapCellValue::Integer(ref arity) => {
|
||||
arity.to_usize().unwrap()
|
||||
}
|
||||
HeapCellValue::Addr(Addr::Fixnum(arity)) => {
|
||||
usize::try_from(*arity).unwrap()
|
||||
}
|
||||
_ => {
|
||||
unreachable!()
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
unreachable!()
|
||||
}
|
||||
@@ -302,7 +323,7 @@ impl Machine {
|
||||
if addrs.is_empty() {
|
||||
self.make_undefined(name.clone(), arity);
|
||||
}
|
||||
|
||||
|
||||
self.print_new_dynamic_clause(addrs, name.clone(), arity)
|
||||
}
|
||||
Err(err) => {
|
||||
|
||||
@@ -6,6 +6,7 @@ use crate::prolog::machine::machine_indices::*;
|
||||
use crate::prolog::machine::partial_string::*;
|
||||
use crate::prolog::machine::raw_block::*;
|
||||
|
||||
use std::convert::TryFrom;
|
||||
use std::mem;
|
||||
use std::ops::{Index, IndexMut};
|
||||
use std::ptr;
|
||||
@@ -202,6 +203,9 @@ impl<T: RawBlockTraits> HeapTemplate<T> {
|
||||
Constant::EmptyList => {
|
||||
Addr::EmptyList
|
||||
}
|
||||
Constant::Fixnum(n) => {
|
||||
Addr::Fixnum(n)
|
||||
}
|
||||
Constant::Integer(n) => {
|
||||
Addr::Con(self.push(HeapCellValue::Integer(n)))
|
||||
}
|
||||
@@ -252,26 +256,6 @@ impl<T: RawBlockTraits> HeapTemplate<T> {
|
||||
h
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate)
|
||||
fn rational_at(&self, h: usize) -> bool {
|
||||
if let HeapCellValue::Rational(_) = &self[h] {
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate)
|
||||
fn integer_at(&self, h: usize) -> bool {
|
||||
if let HeapCellValue::Integer(_) = &self[h] {
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate)
|
||||
fn atom_at(&self, h: usize) -> bool {
|
||||
@@ -475,6 +459,7 @@ impl<T: RawBlockTraits> HeapTemplate<T> {
|
||||
fn to_local_code_ptr(&self, addr: &Addr) -> Option<LocalCodePtr> {
|
||||
let extract_integer = |s: usize| -> Option<usize> {
|
||||
match &self[s] {
|
||||
&HeapCellValue::Addr(Addr::Fixnum(n)) => usize::try_from(n).ok(),
|
||||
&HeapCellValue::Integer(ref n) => n.to_usize(),
|
||||
_ => None
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ use indexmap::IndexMap;
|
||||
use std::cell::RefCell;
|
||||
use std::cmp::Ordering;
|
||||
use std::collections::{BTreeMap, VecDeque};
|
||||
use std::convert::TryFrom;
|
||||
use std::mem;
|
||||
use std::ops::{Add, AddAssign, Sub, SubAssign};
|
||||
use std::rc::Rc;
|
||||
@@ -59,6 +60,7 @@ pub enum Addr {
|
||||
Con(usize),
|
||||
CutPoint(usize),
|
||||
EmptyList,
|
||||
Fixnum(isize),
|
||||
Float(OrderedFloat<f64>),
|
||||
Lis(usize),
|
||||
HeapCell(usize),
|
||||
@@ -155,8 +157,9 @@ impl Addr {
|
||||
#[inline]
|
||||
pub fn is_heap_bound(&self) -> bool {
|
||||
match self {
|
||||
Addr::Char(_) | Addr::CharCode(_) | Addr::EmptyList
|
||||
| Addr::CutPoint(_) | Addr::Usize(_) | Addr::Float(_) => {
|
||||
Addr::Char(_) | Addr::CharCode(_) | Addr::EmptyList |
|
||||
Addr::CutPoint(_) | Addr::Usize(_) | Addr::Fixnum(_) |
|
||||
Addr::Float(_) => {
|
||||
false
|
||||
}
|
||||
_ => {
|
||||
@@ -189,43 +192,47 @@ impl Addr {
|
||||
|
||||
pub(super)
|
||||
fn order_category(&self, heap: &Heap) -> Option<TermOrderCategory> {
|
||||
match self {
|
||||
Addr::HeapCell(_) | Addr::AttrVar(_) | Addr::StackCell(..) => {
|
||||
Some(TermOrderCategory::Variable)
|
||||
}
|
||||
Addr::Float(_) => {
|
||||
Some(TermOrderCategory::FloatingPoint)
|
||||
}
|
||||
&Addr::Con(h) => {
|
||||
match &heap[h] {
|
||||
HeapCellValue::Atom(..) => {
|
||||
Some(TermOrderCategory::Atom)
|
||||
}
|
||||
HeapCellValue::Integer(_) => {
|
||||
Some(TermOrderCategory::Integer)
|
||||
}
|
||||
HeapCellValue::Rational(_) => {
|
||||
Some(TermOrderCategory::Integer)
|
||||
}
|
||||
HeapCellValue::DBRef(_) => {
|
||||
None
|
||||
}
|
||||
_ => {
|
||||
unreachable!()
|
||||
}
|
||||
}
|
||||
}
|
||||
Addr::Char(_) | Addr::EmptyList => {
|
||||
Some(TermOrderCategory::Atom)
|
||||
}
|
||||
Addr::Usize(_) | Addr::CharCode(_) => {
|
||||
match Number::try_from((*self, heap)) {
|
||||
Ok(Number::Integer(_)) | Ok(Number::Fixnum(_)) | Ok(Number::Rational(_)) => {
|
||||
Some(TermOrderCategory::Integer)
|
||||
}
|
||||
Addr::Lis(_) | Addr::PStrLocation(..) | Addr::Str(_) => {
|
||||
Some(TermOrderCategory::Compound)
|
||||
Ok(Number::Float(_)) => {
|
||||
Some(TermOrderCategory::FloatingPoint)
|
||||
}
|
||||
Addr::CutPoint(_) | Addr::Stream(_) => {
|
||||
None
|
||||
_ => {
|
||||
match self {
|
||||
Addr::HeapCell(_) | Addr::AttrVar(_) | Addr::StackCell(..) => {
|
||||
Some(TermOrderCategory::Variable)
|
||||
}
|
||||
Addr::Float(_) => {
|
||||
Some(TermOrderCategory::FloatingPoint)
|
||||
}
|
||||
&Addr::Con(h) => {
|
||||
match &heap[h] {
|
||||
HeapCellValue::Atom(..) => {
|
||||
Some(TermOrderCategory::Atom)
|
||||
}
|
||||
HeapCellValue::DBRef(_) => {
|
||||
None
|
||||
}
|
||||
_ => {
|
||||
unreachable!()
|
||||
}
|
||||
}
|
||||
}
|
||||
Addr::Char(_) | Addr::EmptyList => {
|
||||
Some(TermOrderCategory::Atom)
|
||||
}
|
||||
Addr::CharCode(_) | Addr::Fixnum(_) | Addr::Usize(_) => {
|
||||
Some(TermOrderCategory::Integer)
|
||||
}
|
||||
Addr::Lis(_) | Addr::PStrLocation(..) | Addr::Str(_) => {
|
||||
Some(TermOrderCategory::Compound)
|
||||
}
|
||||
Addr::CutPoint(_) | Addr::Stream(_) => {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -257,13 +264,16 @@ impl Addr {
|
||||
&Addr::EmptyList => {
|
||||
Some(Constant::EmptyList)
|
||||
}
|
||||
&Addr::Fixnum(n) => {
|
||||
Some(Constant::Fixnum(n))
|
||||
}
|
||||
&Addr::Float(f) => {
|
||||
Some(Constant::Float(f))
|
||||
}
|
||||
&Addr::PStrLocation(h, n) => {
|
||||
let mut heap_pstr_iter =
|
||||
machine_st.heap_pstr_iter(Addr::PStrLocation(h, n));
|
||||
|
||||
|
||||
let mut buf = String::new();
|
||||
|
||||
while let Some(Some(c)) = heap_pstr_iter.next() {
|
||||
|
||||
@@ -56,7 +56,7 @@ impl<'a> Iterator for HeapPStrIter<'a> {
|
||||
} else {
|
||||
return None;
|
||||
}
|
||||
|
||||
|
||||
match addr {
|
||||
Addr::PStrLocation(h, n) => {
|
||||
if let &HeapCellValue::PartialString(ref pstr, _) = &self.machine_st.heap[h] {
|
||||
@@ -72,7 +72,7 @@ impl<'a> Iterator for HeapPStrIter<'a> {
|
||||
}
|
||||
Addr::Lis(l) => {
|
||||
let addr = self.machine_st.store(self.machine_st.deref(Addr::HeapCell(l)));
|
||||
|
||||
|
||||
if let Addr::Char(c) = addr {
|
||||
self.focus = Addr::HeapCell(l + 1);
|
||||
return Some(Some(c));
|
||||
@@ -96,7 +96,7 @@ pub(super)
|
||||
fn compare_pstr<'a>(
|
||||
pstr_iter: HeapPStrIter<'a>,
|
||||
mut c_iter: impl Iterator<Item = char>,
|
||||
) -> bool {
|
||||
) -> bool {
|
||||
for opt_c in pstr_iter {
|
||||
match opt_c {
|
||||
Some(_) => {
|
||||
@@ -965,7 +965,7 @@ pub(crate) trait CallPolicy: Any {
|
||||
let a1 = machine_st[r];
|
||||
let n2 = machine_st.get_number(at)?;
|
||||
|
||||
let n2 = Addr::Con(machine_st.heap.push(n2.into()));
|
||||
let n2 = machine_st.heap.put_constant(n2.into());
|
||||
machine_st.unify(a1, n2);
|
||||
|
||||
return_from_clause!(machine_st.last_call, machine_st)
|
||||
|
||||
@@ -21,6 +21,7 @@ use crate::prolog::rug::Integer;
|
||||
use indexmap::{IndexMap, IndexSet};
|
||||
|
||||
use std::cmp::Ordering;
|
||||
use std::convert::TryFrom;
|
||||
use std::rc::Rc;
|
||||
|
||||
macro_rules! try_or_fail {
|
||||
@@ -261,8 +262,8 @@ impl MachineState {
|
||||
|
||||
self.fail = true;
|
||||
}
|
||||
(Addr::PStrLocation(h, n), Addr::Lis(l))
|
||||
| (Addr::Lis(l), Addr::PStrLocation(h, n)) => {
|
||||
(Addr::PStrLocation(h, n), Addr::Lis(l)) |
|
||||
(Addr::Lis(l), Addr::PStrLocation(h, n)) => {
|
||||
if let HeapCellValue::PartialString(ref pstr, _) = &self.heap[h] {
|
||||
if let Some(c) = pstr.range_from(n ..).next() {
|
||||
pdl.push(Addr::PStrLocation(h, n + c.len_utf8()));
|
||||
@@ -369,16 +370,17 @@ impl MachineState {
|
||||
) if db_ref_1 == db_ref_2 => {
|
||||
}
|
||||
(
|
||||
&HeapCellValue::Integer(ref n1),
|
||||
&HeapCellValue::Integer(ref n2),
|
||||
) if &**n1 == &**n2 => {
|
||||
}
|
||||
(
|
||||
&HeapCellValue::Rational(ref n1),
|
||||
&HeapCellValue::Rational(ref n2),
|
||||
) if &**n1 == &**n2 => {
|
||||
}
|
||||
_ => {
|
||||
v1,
|
||||
v2,
|
||||
) => {
|
||||
if let Ok(n1) = Number::try_from(v1) {
|
||||
if let Ok(n2) = Number::try_from(v2) {
|
||||
if n1 == n2 {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
self.fail = true;
|
||||
}
|
||||
}
|
||||
@@ -397,34 +399,31 @@ impl MachineState {
|
||||
}
|
||||
}
|
||||
}
|
||||
(Addr::Usize(n1), Addr::Con(n2)) | (Addr::Con(n2), Addr::Usize(n1)) => {
|
||||
if let HeapCellValue::Integer(ref n2) = &self.heap[n2] {
|
||||
if let Some(n2) = n2.to_usize() {
|
||||
if n1 == n2 {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
self.fail = true;
|
||||
}
|
||||
(Addr::CharCode(n1), Addr::Con(n2)) | (Addr::Con(n2), Addr::CharCode(n1)) => {
|
||||
if let HeapCellValue::Integer(ref n2) = &self.heap[n2] {
|
||||
if let Some(n2) = n2.to_u32() {
|
||||
if n1 == n2 {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
self.fail = true;
|
||||
}
|
||||
(Addr::Stream(s1), Addr::Stream(s2)) => {
|
||||
if s1 != s2 {
|
||||
self.fail = true;
|
||||
}
|
||||
}
|
||||
(v, Addr::Con(h)) | (Addr::Con(h), v) => {
|
||||
if let Ok(n1) = Number::try_from(&self.heap[h]) {
|
||||
if let Ok(v) = Number::try_from(&HeapCellValue::Addr(v)) {
|
||||
if n1 == v {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
self.fail = true;
|
||||
}
|
||||
(a1, a2) => {
|
||||
if let Ok(n1) = Number::try_from(&HeapCellValue::Addr(a1)) {
|
||||
if let Ok(n2) = Number::try_from(&HeapCellValue::Addr(a2)) {
|
||||
if n1 == n2 {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if a1 != a2 {
|
||||
self.fail = true;
|
||||
}
|
||||
@@ -481,8 +480,8 @@ impl MachineState {
|
||||
|
||||
self.fail = true;
|
||||
}
|
||||
(Addr::PStrLocation(h, n), Addr::Lis(l))
|
||||
| (Addr::Lis(l), Addr::PStrLocation(h, n)) => {
|
||||
(Addr::PStrLocation(h, n), Addr::Lis(l)) |
|
||||
(Addr::Lis(l), Addr::PStrLocation(h, n)) => {
|
||||
if let HeapCellValue::PartialString(ref pstr, _) = &self.heap[h] {
|
||||
if let Some(c) = pstr.range_from(n ..).next() {
|
||||
pdl.push(Addr::PStrLocation(h, n + c.len_utf8()));
|
||||
@@ -585,16 +584,17 @@ impl MachineState {
|
||||
) if db_ref_1 == db_ref_2 => {
|
||||
}
|
||||
(
|
||||
&HeapCellValue::Integer(ref n1),
|
||||
&HeapCellValue::Integer(ref n2),
|
||||
) if &**n1 == &**n2 => {
|
||||
}
|
||||
(
|
||||
&HeapCellValue::Rational(ref n1),
|
||||
&HeapCellValue::Rational(ref n2),
|
||||
) if &**n1 == &**n2 => {
|
||||
}
|
||||
_ => {
|
||||
v1,
|
||||
v2,
|
||||
) => {
|
||||
if let Ok(n1) = Number::try_from(v1) {
|
||||
if let Ok(n2) = Number::try_from(v2) {
|
||||
if n1 == n2 {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
self.fail = true;
|
||||
}
|
||||
}
|
||||
@@ -613,34 +613,31 @@ impl MachineState {
|
||||
}
|
||||
}
|
||||
}
|
||||
(Addr::Usize(n1), Addr::Con(n2)) | (Addr::Con(n2), Addr::Usize(n1)) => {
|
||||
if let HeapCellValue::Integer(ref n2) = &self.heap[n2] {
|
||||
if let Some(n2) = n2.to_usize() {
|
||||
if n1 == n2 {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
self.fail = true;
|
||||
}
|
||||
(Addr::CharCode(n1), Addr::Con(n2)) | (Addr::Con(n2), Addr::CharCode(n1)) => {
|
||||
if let HeapCellValue::Integer(ref n2) = &self.heap[n2] {
|
||||
if let Some(n2) = n2.to_u32() {
|
||||
if n1 == n2 {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
self.fail = true;
|
||||
}
|
||||
(Addr::Stream(s1), Addr::Stream(s2)) => {
|
||||
if s1 != s2 {
|
||||
self.fail = true;
|
||||
}
|
||||
}
|
||||
(v, Addr::Con(h)) | (Addr::Con(h), v) => {
|
||||
if let Ok(n1) = Number::try_from(&self.heap[h]) {
|
||||
if let Ok(v) = Number::try_from(&HeapCellValue::Addr(v)) {
|
||||
if n1 == v {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
self.fail = true;
|
||||
}
|
||||
(a1, a2) => {
|
||||
if let Ok(n1) = Number::try_from(&HeapCellValue::Addr(a1)) {
|
||||
if let Ok(n2) = Number::try_from(&HeapCellValue::Addr(a2)) {
|
||||
if n1 == n2 {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if a1 != a2 {
|
||||
self.fail = true;
|
||||
}
|
||||
@@ -791,6 +788,9 @@ impl MachineState {
|
||||
}
|
||||
HeapCellValue::Integer(ref n1) => {
|
||||
match c {
|
||||
Constant::Fixnum(n2) => {
|
||||
n1.to_isize() != Some(*n2)
|
||||
}
|
||||
Constant::Integer(ref n2) => {
|
||||
n1 != n2
|
||||
}
|
||||
@@ -919,8 +919,7 @@ impl MachineState {
|
||||
let n1 = try_or_fail!(self, self.get_number(a1));
|
||||
let n2 = try_or_fail!(self, self.get_number(a2));
|
||||
|
||||
self.interms[t - 1] =
|
||||
Number::Integer(Rc::new(try_or_fail!(self, self.gcd(n1, n2))));
|
||||
self.interms[t - 1] = try_or_fail!(self, self.gcd(n1, n2));
|
||||
self.p += 1;
|
||||
}
|
||||
&ArithmeticInstruction::Pow(ref a1, ref a2, t) => {
|
||||
@@ -944,16 +943,14 @@ impl MachineState {
|
||||
let n1 = try_or_fail!(self, self.get_number(a1));
|
||||
let n2 = try_or_fail!(self, self.get_number(a2));
|
||||
|
||||
self.interms[t - 1] =
|
||||
Number::Integer(Rc::new(try_or_fail!(self, self.int_floor_div(n1, n2))));
|
||||
self.interms[t - 1] = try_or_fail!(self, self.int_floor_div(n1, n2));
|
||||
self.p += 1;
|
||||
}
|
||||
&ArithmeticInstruction::IDiv(ref a1, ref a2, t) => {
|
||||
let n1 = try_or_fail!(self, self.get_number(a1));
|
||||
let n2 = try_or_fail!(self, self.get_number(a2));
|
||||
|
||||
self.interms[t - 1] =
|
||||
Number::Integer(Rc::new(try_or_fail!(self, self.idiv(n1, n2))));
|
||||
self.interms[t - 1] = try_or_fail!(self, self.idiv(n1, n2));
|
||||
self.p += 1;
|
||||
}
|
||||
&ArithmeticInstruction::Abs(ref a1, t) => {
|
||||
@@ -965,7 +962,7 @@ impl MachineState {
|
||||
&ArithmeticInstruction::Sign(ref a1, t) => {
|
||||
let n = try_or_fail!(self, self.get_number(a1));
|
||||
|
||||
self.interms[t - 1] = Number::Integer(Rc::new(self.sign(n)));
|
||||
self.interms[t - 1] = self.sign(n);
|
||||
self.p += 1;
|
||||
}
|
||||
&ArithmeticInstruction::Neg(ref a1, t) => {
|
||||
@@ -977,8 +974,7 @@ impl MachineState {
|
||||
&ArithmeticInstruction::BitwiseComplement(ref a1, t) => {
|
||||
let n1 = try_or_fail!(self, self.get_number(a1));
|
||||
|
||||
self.interms[t - 1] =
|
||||
Number::Integer(Rc::new(try_or_fail!(self, self.bitwise_complement(n1))));
|
||||
self.interms[t - 1] = try_or_fail!(self, self.bitwise_complement(n1));
|
||||
self.p += 1;
|
||||
}
|
||||
&ArithmeticInstruction::Div(ref a1, ref a2, t) => {
|
||||
@@ -992,56 +988,49 @@ impl MachineState {
|
||||
let n1 = try_or_fail!(self, self.get_number(a1));
|
||||
let n2 = try_or_fail!(self, self.get_number(a2));
|
||||
|
||||
self.interms[t - 1] =
|
||||
Number::Integer(Rc::new(try_or_fail!(self, self.shr(n1, n2))));
|
||||
self.interms[t - 1] = try_or_fail!(self, self.shr(n1, n2));
|
||||
self.p += 1;
|
||||
}
|
||||
&ArithmeticInstruction::Shl(ref a1, ref a2, t) => {
|
||||
let n1 = try_or_fail!(self, self.get_number(a1));
|
||||
let n2 = try_or_fail!(self, self.get_number(a2));
|
||||
|
||||
self.interms[t - 1] =
|
||||
Number::Integer(Rc::new(try_or_fail!(self, self.shl(n1, n2))));
|
||||
self.interms[t - 1] = try_or_fail!(self, self.shl(n1, n2));
|
||||
self.p += 1;
|
||||
}
|
||||
&ArithmeticInstruction::Xor(ref a1, ref a2, t) => {
|
||||
let n1 = try_or_fail!(self, self.get_number(a1));
|
||||
let n2 = try_or_fail!(self, self.get_number(a2));
|
||||
|
||||
self.interms[t - 1] =
|
||||
Number::Integer(Rc::new(try_or_fail!(self, self.xor(n1, n2))));
|
||||
self.interms[t - 1] = try_or_fail!(self, self.xor(n1, n2));
|
||||
self.p += 1;
|
||||
}
|
||||
&ArithmeticInstruction::And(ref a1, ref a2, t) => {
|
||||
let n1 = try_or_fail!(self, self.get_number(a1));
|
||||
let n2 = try_or_fail!(self, self.get_number(a2));
|
||||
|
||||
self.interms[t - 1] =
|
||||
Number::Integer(Rc::new(try_or_fail!(self, self.and(n1, n2))));
|
||||
self.interms[t - 1] = try_or_fail!(self, self.and(n1, n2));
|
||||
self.p += 1;
|
||||
}
|
||||
&ArithmeticInstruction::Or(ref a1, ref a2, t) => {
|
||||
let n1 = try_or_fail!(self, self.get_number(a1));
|
||||
let n2 = try_or_fail!(self, self.get_number(a2));
|
||||
|
||||
self.interms[t - 1] =
|
||||
Number::Integer(Rc::new(try_or_fail!(self, self.or(n1, n2))));
|
||||
self.interms[t - 1] = try_or_fail!(self, self.or(n1, n2));
|
||||
self.p += 1;
|
||||
}
|
||||
&ArithmeticInstruction::Mod(ref a1, ref a2, t) => {
|
||||
let n1 = try_or_fail!(self, self.get_number(a1));
|
||||
let n2 = try_or_fail!(self, self.get_number(a2));
|
||||
|
||||
self.interms[t - 1] =
|
||||
Number::Integer(Rc::new(try_or_fail!(self, self.modulus(n1, n2))));
|
||||
self.interms[t - 1] = try_or_fail!(self, self.modulus(n1, n2));
|
||||
self.p += 1;
|
||||
}
|
||||
&ArithmeticInstruction::Rem(ref a1, ref a2, t) => {
|
||||
let n1 = try_or_fail!(self, self.get_number(a1));
|
||||
let n2 = try_or_fail!(self, self.get_number(a2));
|
||||
|
||||
self.interms[t - 1] =
|
||||
Number::Integer(Rc::new(try_or_fail!(self, self.remainder(n1, n2))));
|
||||
self.interms[t - 1] = try_or_fail!(self, self.remainder(n1, n2));
|
||||
self.p += 1;
|
||||
}
|
||||
&ArithmeticInstruction::Cos(ref a1, t) => {
|
||||
@@ -1120,29 +1109,25 @@ impl MachineState {
|
||||
&ArithmeticInstruction::Truncate(ref a1, t) => {
|
||||
let n1 = try_or_fail!(self, self.get_number(a1));
|
||||
|
||||
self.interms[t - 1] =
|
||||
Number::Integer(Rc::new(self.truncate(n1)));
|
||||
self.interms[t - 1] = self.truncate(n1);
|
||||
self.p += 1;
|
||||
}
|
||||
&ArithmeticInstruction::Round(ref a1, t) => {
|
||||
let n1 = try_or_fail!(self, self.get_number(a1));
|
||||
|
||||
self.interms[t - 1] =
|
||||
Number::Integer(Rc::new(try_or_fail!(self, self.round(n1))));
|
||||
self.interms[t - 1] = try_or_fail!(self, self.round(n1));
|
||||
self.p += 1;
|
||||
}
|
||||
&ArithmeticInstruction::Ceiling(ref a1, t) => {
|
||||
let n1 = try_or_fail!(self, self.get_number(a1));
|
||||
|
||||
self.interms[t - 1] =
|
||||
Number::Integer(Rc::new(self.ceiling(n1)));
|
||||
self.interms[t - 1] = self.ceiling(n1);
|
||||
self.p += 1;
|
||||
}
|
||||
&ArithmeticInstruction::Floor(ref a1, t) => {
|
||||
let n1 = try_or_fail!(self, self.get_number(a1));
|
||||
|
||||
self.interms[t - 1] =
|
||||
Number::Integer(Rc::new(self.floor(n1)));
|
||||
self.interms[t - 1] = self.floor(n1);
|
||||
self.p += 1;
|
||||
}
|
||||
&ArithmeticInstruction::Plus(ref a1, t) => {
|
||||
@@ -1332,7 +1317,7 @@ impl MachineState {
|
||||
}
|
||||
}
|
||||
Addr::Char(_) | Addr::CharCode(_) | Addr::Con(_) | Addr::CutPoint(_) |
|
||||
Addr::EmptyList | Addr::Float(_) | Addr::Usize(_) => {
|
||||
Addr::EmptyList | Addr::Fixnum(_) | Addr::Float(_) | Addr::Usize(_) => {
|
||||
c
|
||||
}
|
||||
Addr::Lis(_) => {
|
||||
@@ -1624,19 +1609,35 @@ impl MachineState {
|
||||
Addr::HeapCell(_) | Addr::StackCell(..) => { // 8.5.2.3 a)
|
||||
return Err(self.error_form(MachineError::instantiation_error(), stub))
|
||||
}
|
||||
Addr::Con(h) => {
|
||||
if let HeapCellValue::Integer(n) = self.heap.clone(h) {
|
||||
if &*n < &0 { // 8.5.2.3 e)
|
||||
let n = Number::Integer(n);
|
||||
let dom_err = MachineError::domain_error(
|
||||
DomainErrorType::NotLessThanZero,
|
||||
n,
|
||||
);
|
||||
addr => {
|
||||
let n =
|
||||
match Number::try_from((addr, &self.heap)) {
|
||||
Ok(Number::Fixnum(n)) => Integer::from(n),
|
||||
Ok(Number::Integer(n)) => Integer::from(n.as_ref()),
|
||||
_ => {
|
||||
return Err(self.error_form(
|
||||
MachineError::type_error(
|
||||
self.heap.h(),
|
||||
ValidType::Integer,
|
||||
addr,
|
||||
),
|
||||
stub,
|
||||
));
|
||||
}
|
||||
};
|
||||
|
||||
return Err(self.error_form(dom_err, stub));
|
||||
}
|
||||
if n < 0 { // 8.5.2.3 e)
|
||||
let n = Number::from(n);
|
||||
let dom_err = MachineError::domain_error(
|
||||
DomainErrorType::NotLessThanZero,
|
||||
n,
|
||||
);
|
||||
|
||||
let n = match n.to_usize() {
|
||||
return Err(self.error_form(dom_err, stub));
|
||||
}
|
||||
|
||||
let n =
|
||||
match n.to_usize() {
|
||||
Some(n) => n,
|
||||
None => {
|
||||
self.fail = true;
|
||||
@@ -1644,88 +1645,68 @@ impl MachineState {
|
||||
}
|
||||
};
|
||||
|
||||
let term = self.store(self.deref(self[temp_v!(2)]));
|
||||
let term = self.store(self.deref(self[temp_v!(2)]));
|
||||
|
||||
match term {
|
||||
Addr::HeapCell(_) | Addr::StackCell(..) => { // 8.5.2.3 b)
|
||||
return Err(self.error_form(MachineError::instantiation_error(), stub))
|
||||
match term {
|
||||
Addr::HeapCell(_) | Addr::StackCell(..) | Addr::AttrVar(_) => { // 8.5.2.3 b)
|
||||
return Err(self.error_form(MachineError::instantiation_error(), stub))
|
||||
}
|
||||
Addr::Str(o) => match self.heap.clone(o) {
|
||||
HeapCellValue::NamedStr(arity, _, _) if 1 <= n && n <= arity => {
|
||||
let a3 = self[temp_v!(3)];
|
||||
let h_a = Addr::HeapCell(o + n);
|
||||
|
||||
self.unify(a3, h_a);
|
||||
}
|
||||
Addr::Str(o) => match self.heap.clone(o) {
|
||||
HeapCellValue::NamedStr(arity, _, _) if 1 <= n && n <= arity => {
|
||||
let a3 = self[temp_v!(3)];
|
||||
let h_a = Addr::HeapCell(o + n);
|
||||
|
||||
self.unify(a3, h_a);
|
||||
}
|
||||
_ => {
|
||||
self.fail = true;
|
||||
}
|
||||
},
|
||||
Addr::Lis(l) => {
|
||||
if n == 1 || n == 2 {
|
||||
let a3 = self[temp_v!(3)];
|
||||
let h_a = Addr::HeapCell(l + n - 1);
|
||||
|
||||
self.unify(a3, h_a);
|
||||
} else {
|
||||
self.fail = true;
|
||||
}
|
||||
_ => {
|
||||
self.fail = true;
|
||||
}
|
||||
Addr::PStrLocation(h, offset) => {
|
||||
if n == 1 || n == 2 {
|
||||
let a3 = self[temp_v!(3)];
|
||||
let h_a =
|
||||
if let HeapCellValue::PartialString(ref pstr, _) = &self.heap[h] {
|
||||
if let Some(c) = pstr.range_from(offset ..).next() {
|
||||
if n == 1 {
|
||||
Addr::Char(c)
|
||||
} else {
|
||||
Addr::PStrLocation(h, offset + c.len_utf8())
|
||||
}
|
||||
},
|
||||
Addr::Lis(l) => {
|
||||
if n == 1 || n == 2 {
|
||||
let a3 = self[temp_v!(3)];
|
||||
let h_a = Addr::HeapCell(l + n - 1);
|
||||
|
||||
self.unify(a3, h_a);
|
||||
} else {
|
||||
self.fail = true;
|
||||
}
|
||||
}
|
||||
Addr::PStrLocation(h, offset) => {
|
||||
if n == 1 || n == 2 {
|
||||
let a3 = self[temp_v!(3)];
|
||||
let h_a =
|
||||
if let HeapCellValue::PartialString(ref pstr, _) = &self.heap[h] {
|
||||
if let Some(c) = pstr.range_from(offset ..).next() {
|
||||
if n == 1 {
|
||||
Addr::Char(c)
|
||||
} else {
|
||||
unreachable!()
|
||||
Addr::PStrLocation(h, offset + c.len_utf8())
|
||||
}
|
||||
} else {
|
||||
unreachable!()
|
||||
};
|
||||
}
|
||||
} else {
|
||||
unreachable!()
|
||||
};
|
||||
|
||||
self.unify(a3, h_a);
|
||||
} else {
|
||||
self.fail = true;
|
||||
}
|
||||
}
|
||||
_ => { // 8.5.2.3 d)
|
||||
return Err(self.error_form(
|
||||
MachineError::type_error(
|
||||
self.heap.h(),
|
||||
ValidType::Compound,
|
||||
term,
|
||||
),
|
||||
stub,
|
||||
))
|
||||
self.unify(a3, h_a);
|
||||
} else {
|
||||
self.fail = true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return Err(self.error_form(
|
||||
MachineError::type_error(
|
||||
self.heap.h(),
|
||||
ValidType::Integer,
|
||||
Addr::HeapCell(h),
|
||||
),
|
||||
stub,
|
||||
))
|
||||
_ => { // 8.5.2.3 d)
|
||||
return Err(self.error_form(
|
||||
MachineError::type_error(
|
||||
self.heap.h(),
|
||||
ValidType::Compound,
|
||||
term,
|
||||
),
|
||||
stub,
|
||||
))
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => { // 8.5.2.3 c)
|
||||
return Err(self.error_form(
|
||||
MachineError::type_error(
|
||||
self.heap.h(),
|
||||
ValidType::Integer,
|
||||
n,
|
||||
),
|
||||
stub,
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
@@ -1747,7 +1728,8 @@ impl MachineState {
|
||||
self.p += 1;
|
||||
}
|
||||
|
||||
pub(super) fn compare_term(&mut self, qt: CompareTermQT) {
|
||||
pub(super)
|
||||
fn compare_term(&mut self, qt: CompareTermQT) {
|
||||
let a1 = self[temp_v!(1)];
|
||||
let a2 = self[temp_v!(2)];
|
||||
|
||||
@@ -1804,18 +1786,10 @@ impl MachineState {
|
||||
(Addr::Con(h1), Addr::Con(h2)) => {
|
||||
match (&self.heap[h1], &self.heap[h2]) {
|
||||
(
|
||||
&HeapCellValue::Integer(ref n1),
|
||||
&HeapCellValue::Integer(ref n2),
|
||||
&HeapCellValue::Atom(ref n1, ref spec_1),
|
||||
&HeapCellValue::Atom(ref n2, ref spec_2),
|
||||
) => {
|
||||
if n1 != n2 {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
(
|
||||
&HeapCellValue::Rational(ref n1),
|
||||
&HeapCellValue::Rational(ref n2),
|
||||
) => {
|
||||
if n1 != n2 {
|
||||
if n1 != n2 || spec_1 != spec_2 {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -1828,14 +1802,17 @@ impl MachineState {
|
||||
}
|
||||
}
|
||||
(
|
||||
&HeapCellValue::Atom(ref n1, ref spec_1),
|
||||
&HeapCellValue::Atom(ref n2, ref spec_2),
|
||||
v1,
|
||||
v2,
|
||||
) => {
|
||||
if n1 != n2 || spec_1 != spec_2 {
|
||||
return true;
|
||||
if let Ok(n1) = Number::try_from(v1) {
|
||||
if let Ok(n2) = Number::try_from(v2) {
|
||||
if n1 == n2 {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -1852,25 +1829,26 @@ impl MachineState {
|
||||
}
|
||||
}
|
||||
}
|
||||
(Addr::Usize(n1), Addr::Con(n2)) | (Addr::Con(n2), Addr::Usize(n1)) => {
|
||||
if let HeapCellValue::Integer(ref n2) = &self.heap[n2] {
|
||||
if let Some(n2) = n2.to_usize() {
|
||||
(Addr::CharCode(n1), v2) | (v2, Addr::CharCode(n1)) => {
|
||||
if let Ok(n2) = Number::try_from((v2, &self.heap)) {
|
||||
if let Some(n2) = n2.to_u32() {
|
||||
if n1 != n2 {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
(Addr::CharCode(n1), Addr::Con(n2)) | (Addr::Con(n2), Addr::CharCode(n1)) => {
|
||||
if let HeapCellValue::Integer(ref n2) = &self.heap[n2] {
|
||||
if let Some(n2) = n2.to_u32() {
|
||||
if n1 == n2 {
|
||||
(a1, a2) => {
|
||||
if let Ok(n1) = Number::try_from((a1, &self.heap)) {
|
||||
if let Ok(n2) = Number::try_from((a2, &self.heap)) {
|
||||
if n1 != n2 {
|
||||
return true;
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
(a1, a2) => {
|
||||
|
||||
if a1 != a2 {
|
||||
return true;
|
||||
}
|
||||
@@ -1919,74 +1897,62 @@ impl MachineState {
|
||||
Addr::Con(h1),
|
||||
Addr::Con(h2),
|
||||
) => {
|
||||
match (&self.heap[h1], &self.heap[h2]) {
|
||||
(
|
||||
HeapCellValue::Integer(ref n1),
|
||||
HeapCellValue::Integer(ref n2),
|
||||
) => {
|
||||
if &*n1 != &*n2 {
|
||||
return Some(n1.cmp(&*n2));
|
||||
if let Ok(n1) = Number::try_from(&self.heap[h1]) {
|
||||
if let Ok(n2) = Number::try_from(&self.heap[h2]) {
|
||||
if n1 != n2 {
|
||||
return Some(n1.cmp(&n2));
|
||||
}
|
||||
}
|
||||
(
|
||||
HeapCellValue::Rational(ref n1),
|
||||
HeapCellValue::Integer(ref n2),
|
||||
) => {
|
||||
if &**n1 != &**n2 {
|
||||
return n1.as_ref().partial_cmp(n2.as_ref());
|
||||
}
|
||||
}
|
||||
(
|
||||
HeapCellValue::Integer(ref n1),
|
||||
HeapCellValue::Rational(ref n2),
|
||||
) => {
|
||||
if &**n1 != &**n2 {
|
||||
return n1.as_ref().partial_cmp(n2.as_ref());
|
||||
}
|
||||
}
|
||||
(
|
||||
HeapCellValue::Rational(ref r1),
|
||||
HeapCellValue::Rational(ref r2),
|
||||
) => {
|
||||
if &*r1 != &*r2 {
|
||||
return Some(r1.cmp(r2));
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
} else {
|
||||
unreachable!()
|
||||
}
|
||||
} else {
|
||||
unreachable!()
|
||||
}
|
||||
}
|
||||
(Addr::Usize(n1), Addr::Usize(n2)) => {
|
||||
if n1 != n2 {
|
||||
return Some(n1.cmp(&n2));
|
||||
}
|
||||
}
|
||||
(Addr::CharCode(n1), Addr::CharCode(n2)) => {
|
||||
if n1 != n2 {
|
||||
return Some(n1.cmp(&n2));
|
||||
}
|
||||
}
|
||||
(Addr::Usize(n1), Addr::Con(n2)) | (Addr::Con(n2), Addr::Usize(n1)) => {
|
||||
if let HeapCellValue::Integer(ref n2) = &self.heap[n2] {
|
||||
if let Some(n2) = n2.to_usize() {
|
||||
(
|
||||
Addr::Con(h1),
|
||||
v2,
|
||||
) => {
|
||||
if let Ok(n1) = Number::try_from(&self.heap[h1]) {
|
||||
if let Ok(n2) = Number::try_from(&HeapCellValue::Addr(v2)) {
|
||||
if n1 != n2 {
|
||||
return Some(n1.cmp(&n2));
|
||||
}
|
||||
} else {
|
||||
unreachable!()
|
||||
}
|
||||
} else {
|
||||
unreachable!()
|
||||
}
|
||||
}
|
||||
(Addr::CharCode(n1), Addr::Con(n2)) | (Addr::Con(n2), Addr::CharCode(n1)) => {
|
||||
if let HeapCellValue::Integer(ref n2) = &self.heap[n2] {
|
||||
if let Some(n2) = n2.to_u32() {
|
||||
(
|
||||
v1,
|
||||
Addr::Con(h2),
|
||||
) => {
|
||||
if let Ok(n1) = Number::try_from(&HeapCellValue::Addr(v1)) {
|
||||
if let Ok(n2) = Number::try_from(&self.heap[h2]) {
|
||||
if n1 != n2 {
|
||||
return Some(n1.cmp(&n2));
|
||||
}
|
||||
} else {
|
||||
unreachable!()
|
||||
}
|
||||
} else {
|
||||
unreachable!()
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
unreachable!()
|
||||
(v1, v2) => {
|
||||
if let Ok(n1) = Number::try_from(&HeapCellValue::Addr(v1)) {
|
||||
if let Ok(n2) = Number::try_from(&HeapCellValue::Addr(v2)) {
|
||||
if n1 != n2 {
|
||||
return Some(n1.cmp(&n2));
|
||||
}
|
||||
} else {
|
||||
unreachable!()
|
||||
}
|
||||
} else {
|
||||
unreachable!()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2330,34 +2296,34 @@ impl MachineState {
|
||||
&InlinedClauseType::IsInteger(r1) => {
|
||||
let d = self.store(self.deref(self[r1]));
|
||||
|
||||
match d {
|
||||
Addr::Con(h) => {
|
||||
match &self.heap[h] {
|
||||
HeapCellValue::Integer(_) => {
|
||||
match Number::try_from((d, &self.heap)) {
|
||||
Ok(Number::Fixnum(_)) => {
|
||||
self.p += 1;
|
||||
}
|
||||
Ok(Number::Integer(_)) => {
|
||||
self.p += 1;
|
||||
}
|
||||
Ok(Number::Rational(n)) => {
|
||||
if n.denom() == &1 {
|
||||
self.p += 1;
|
||||
} else {
|
||||
self.fail = true;
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
match d {
|
||||
Addr::CharCode(_) => {
|
||||
self.p += 1;
|
||||
}
|
||||
HeapCellValue::Rational(ref r) => {
|
||||
if r.denom() == &1 {
|
||||
self.p += 1;
|
||||
} else {
|
||||
self.fail = true;
|
||||
}
|
||||
Addr::Char(_) if self.flags.double_quotes.is_codes() => {
|
||||
self.p += 1;
|
||||
}
|
||||
_ => {
|
||||
self.fail = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
Addr::CharCode(_) | Addr::Usize(_) => {
|
||||
self.p += 1;
|
||||
}
|
||||
Addr::Char(_) if self.flags.double_quotes.is_codes() => {
|
||||
self.p += 1;
|
||||
}
|
||||
_ => {
|
||||
self.fail = true;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
&InlinedClauseType::IsCompound(r1) => {
|
||||
let d = self.store(self.deref(self[r1]));
|
||||
@@ -2484,8 +2450,8 @@ impl MachineState {
|
||||
Addr::Stream(_) => {
|
||||
self.fail = true;
|
||||
}
|
||||
Addr::Char(_) | Addr::CharCode(_) | Addr::Con(_) | Addr::Float(_) |
|
||||
Addr::EmptyList | Addr::Usize(_) => {
|
||||
Addr::Char(_) | Addr::CharCode(_) | Addr::Con(_) | Addr::Fixnum(_) |
|
||||
Addr::Float(_) | Addr::EmptyList | Addr::Usize(_) => {
|
||||
self.try_functor_unify_components(a1, 0);
|
||||
}
|
||||
Addr::Str(o) => match self.heap.clone(o) {
|
||||
@@ -2510,48 +2476,33 @@ impl MachineState {
|
||||
return Err(self.error_form(MachineError::instantiation_error(), stub));
|
||||
}
|
||||
|
||||
let arity = match arity {
|
||||
Addr::Con(h) => {
|
||||
match &self.heap[h] {
|
||||
&HeapCellValue::Integer(ref n) => {
|
||||
n.to_isize()
|
||||
let arity =
|
||||
match Number::try_from((arity, &self.heap)) {
|
||||
Ok(Number::Fixnum(n)) => Some(n),
|
||||
Ok(Number::Integer(n)) => n.to_isize(),
|
||||
Ok(Number::Rational(n))
|
||||
if n.denom() == &1 => {
|
||||
n.numer().to_isize()
|
||||
},
|
||||
_ =>
|
||||
match arity {
|
||||
Addr::CharCode(c) => {
|
||||
Some(c as isize)
|
||||
}
|
||||
arity => {
|
||||
return Err(
|
||||
self.error_form(
|
||||
MachineError::type_error(
|
||||
self.heap.h(),
|
||||
ValidType::Integer,
|
||||
arity,
|
||||
),
|
||||
stub,
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
&HeapCellValue::Addr(Addr::Usize(n)) => {
|
||||
Some(n as isize)
|
||||
}
|
||||
_ => {
|
||||
return Err(
|
||||
self.error_form(
|
||||
MachineError::type_error(
|
||||
self.heap.h(),
|
||||
ValidType::Integer,
|
||||
arity,
|
||||
),
|
||||
stub,
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
},
|
||||
Addr::Usize(n) => {
|
||||
Some(n as isize)
|
||||
}
|
||||
Addr::CharCode(c) => {
|
||||
Some(c as isize)
|
||||
}
|
||||
arity => {
|
||||
return Err(
|
||||
self.error_form(
|
||||
MachineError::type_error(
|
||||
self.heap.h(),
|
||||
ValidType::Integer,
|
||||
arity,
|
||||
),
|
||||
stub,
|
||||
)
|
||||
);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
let arity = match arity {
|
||||
Some(arity) => {
|
||||
@@ -2579,7 +2530,7 @@ impl MachineState {
|
||||
}
|
||||
|
||||
match name {
|
||||
Addr::Char(_) | Addr::CharCode(_) | Addr::Con(_) | Addr::Float(_) |
|
||||
Addr::Char(_) | Addr::CharCode(_) | Addr::Con(_) | Addr::Fixnum(_) | Addr::Float(_) |
|
||||
Addr::EmptyList | Addr::PStrLocation(..) | Addr::Usize(_) if arity == 0 => {
|
||||
self.unify(a1, name);
|
||||
}
|
||||
@@ -2925,34 +2876,6 @@ impl MachineState {
|
||||
HeapCellValue::Addr(Addr::PStrLocation(..)),
|
||||
) => {
|
||||
}
|
||||
(
|
||||
HeapCellValue::Integer(n1),
|
||||
HeapCellValue::Integer(n2),
|
||||
) => {
|
||||
if &*n1 != &*n2 {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
(
|
||||
HeapCellValue::Rational(n1),
|
||||
HeapCellValue::Rational(n2),
|
||||
) => {
|
||||
if &*n1 != &*n2 {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
(
|
||||
HeapCellValue::Integer(ref n1),
|
||||
HeapCellValue::Rational(ref n2),
|
||||
) |
|
||||
(
|
||||
HeapCellValue::Rational(ref n2),
|
||||
HeapCellValue::Integer(ref n1),
|
||||
) => {
|
||||
if n1.as_ref().partial_cmp(&**n2) == Some(Ordering::Equal) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
(
|
||||
HeapCellValue::Atom(ref n1, ref spec_1),
|
||||
HeapCellValue::Atom(ref n2, ref spec_2),
|
||||
@@ -2970,15 +2893,34 @@ impl MachineState {
|
||||
}
|
||||
}
|
||||
(
|
||||
HeapCellValue::Addr(a1),
|
||||
HeapCellValue::Addr(a2),
|
||||
v1,
|
||||
v2,
|
||||
) => {
|
||||
if a1 != a2 {
|
||||
return true;
|
||||
if let Ok(n1) = Number::try_from(v1) {
|
||||
if let Ok(n2) = Number::try_from(v2) {
|
||||
if n1 != n2 {
|
||||
return true;
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
match (v1, v2) {
|
||||
(
|
||||
HeapCellValue::Addr(a1),
|
||||
HeapCellValue::Addr(a2),
|
||||
) => {
|
||||
if a1 != a2 {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3051,13 +2993,13 @@ impl MachineState {
|
||||
lco: bool,
|
||||
use_default_cp: bool,
|
||||
) {
|
||||
let interrupted = INTERRUPT.load(std::sync::atomic::Ordering::Relaxed);
|
||||
let interrupted = INTERRUPT.load(std::sync::atomic::Ordering::Relaxed);
|
||||
|
||||
if INTERRUPT.compare_and_swap(interrupted, false, std::sync::atomic::Ordering::Relaxed) {
|
||||
self.reset();
|
||||
self.fail = true;
|
||||
return;
|
||||
}
|
||||
if INTERRUPT.compare_and_swap(interrupted, false, std::sync::atomic::Ordering::Relaxed) {
|
||||
self.reset();
|
||||
self.fail = true;
|
||||
return;
|
||||
}
|
||||
|
||||
let mut default_call_policy: Box<dyn CallPolicy> = Box::new(DefaultCallPolicy {});
|
||||
|
||||
@@ -3192,8 +3134,12 @@ impl MachineState {
|
||||
self.hb = self.heap.h();
|
||||
self.p += offset;
|
||||
}
|
||||
&IndexedChoiceInstruction::Retry(l) => try_or_fail!(self, call_policy.retry(self, l)),
|
||||
&IndexedChoiceInstruction::Trust(l) => try_or_fail!(self, call_policy.trust(self, l)),
|
||||
&IndexedChoiceInstruction::Retry(l) => {
|
||||
try_or_fail!(self, call_policy.retry(self, l));
|
||||
}
|
||||
&IndexedChoiceInstruction::Trust(l) => {
|
||||
try_or_fail!(self, call_policy.trust(self, l));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -3241,7 +3187,9 @@ impl MachineState {
|
||||
&ChoiceInstruction::RetryMeElse(offset) => {
|
||||
try_or_fail!(self, call_policy.retry_me_else(self, offset))
|
||||
}
|
||||
&ChoiceInstruction::TrustMe => try_or_fail!(self, call_policy.trust_me(self)),
|
||||
&ChoiceInstruction::TrustMe => {
|
||||
try_or_fail!(self, call_policy.trust_me(self))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -45,6 +45,7 @@ use crate::prolog::machine::toplevel::*;
|
||||
use indexmap::IndexMap;
|
||||
|
||||
use std::collections::VecDeque;
|
||||
use std::convert::TryFrom;
|
||||
use std::fs::File;
|
||||
use std::mem;
|
||||
use std::ops::Index;
|
||||
@@ -205,11 +206,11 @@ impl SubModuleUser for IndexStore {
|
||||
#[inline]
|
||||
fn current_dir() -> std::path::PathBuf {
|
||||
let mut path_buf = std::path::PathBuf::from(PROJECT_DIR);
|
||||
|
||||
|
||||
// file!() always produces a path relative to PROJECT_DIR.
|
||||
path_buf = path_buf.join(std::path::PathBuf::from(file!()));
|
||||
|
||||
path_buf.pop();
|
||||
path_buf.pop();
|
||||
path_buf
|
||||
}
|
||||
|
||||
@@ -322,34 +323,34 @@ impl Machine {
|
||||
}
|
||||
|
||||
pub fn run_init_code(&mut self, code: Code) -> bool {
|
||||
let old_machine_st = self.sink_to_snapshot();
|
||||
self.machine_st.reset();
|
||||
let old_machine_st = self.sink_to_snapshot();
|
||||
self.machine_st.reset();
|
||||
|
||||
self.code_repo.cached_query = code;
|
||||
self.run_query();
|
||||
self.code_repo.cached_query = code;
|
||||
self.run_query();
|
||||
|
||||
let result = self.machine_st.fail;
|
||||
self.absorb_snapshot(old_machine_st);
|
||||
self.absorb_snapshot(old_machine_st);
|
||||
|
||||
!result
|
||||
}
|
||||
|
||||
pub fn run_top_level(&mut self) {
|
||||
use std::env;
|
||||
use std::env;
|
||||
|
||||
let mut filename_atoms = vec![];
|
||||
let mut filename_atoms = vec![];
|
||||
|
||||
// the first of these is the path to the scryer-prolog executable, so skip
|
||||
// it.
|
||||
for filename in env::args().skip(1) {
|
||||
let atom = clause_name!(filename, self.indices.atom_tbl);
|
||||
filename_atoms.push(HeapCellValue::Atom(atom, None));
|
||||
}
|
||||
// the first of these is the path to the scryer-prolog executable, so skip
|
||||
// it.
|
||||
for filename in env::args().skip(1) {
|
||||
let atom = clause_name!(filename, self.indices.atom_tbl);
|
||||
filename_atoms.push(HeapCellValue::Atom(atom, None));
|
||||
}
|
||||
|
||||
let list_addr =
|
||||
Addr::HeapCell(self.machine_st.heap.to_list(filename_atoms.into_iter()));
|
||||
let list_addr =
|
||||
Addr::HeapCell(self.machine_st.heap.to_list(filename_atoms.into_iter()));
|
||||
|
||||
self.machine_st[temp_v!(1)] = list_addr;
|
||||
self.machine_st[temp_v!(1)] = list_addr;
|
||||
self.machine_st.p = CodePtr::Local(LocalCodePtr::DirEntry(self.toplevel_idx));
|
||||
|
||||
self.run_query();
|
||||
@@ -397,7 +398,7 @@ impl Machine {
|
||||
lib_path.clone(),
|
||||
)
|
||||
);
|
||||
|
||||
|
||||
compile_user_module(&mut wam,
|
||||
Stream::from(LISTS),
|
||||
true,
|
||||
@@ -406,7 +407,7 @@ impl Machine {
|
||||
lib_path.clone(),
|
||||
),
|
||||
);
|
||||
|
||||
|
||||
compile_user_module(&mut wam,
|
||||
Stream::from(ISO_EXT),
|
||||
true,
|
||||
@@ -415,7 +416,7 @@ impl Machine {
|
||||
lib_path.clone(),
|
||||
)
|
||||
);
|
||||
|
||||
|
||||
compile_user_module(&mut wam,
|
||||
Stream::from(SI),
|
||||
true,
|
||||
@@ -539,53 +540,57 @@ impl Machine {
|
||||
|
||||
fn extract_module_export_list(&mut self) -> Result<Vec<ModuleExport>, ParserError>
|
||||
{
|
||||
let mut export_list = self.machine_st[temp_v!(2)].clone();
|
||||
let mut exports = vec![];
|
||||
let mut export_list = self.machine_st[temp_v!(2)].clone();
|
||||
let mut exports = vec![];
|
||||
|
||||
while let Addr::Lis(l) = self.machine_st.store(self.machine_st.deref(export_list)) {
|
||||
match &self.machine_st.heap[l] {
|
||||
&HeapCellValue::Addr(Addr::Str(s)) => {
|
||||
while let Addr::Lis(l) = self.machine_st.store(self.machine_st.deref(export_list)) {
|
||||
match &self.machine_st.heap[l] {
|
||||
&HeapCellValue::Addr(Addr::Str(s)) => {
|
||||
match &self.machine_st.heap[s] {
|
||||
HeapCellValue::NamedStr(arity, ref name, _)
|
||||
if *arity == 2 && name.as_str() == "/" => {
|
||||
let name = match &self.machine_st.heap[s+1] {
|
||||
&HeapCellValue::Atom(ref name, _) =>
|
||||
name.clone(),
|
||||
_ =>
|
||||
unreachable!()
|
||||
};
|
||||
let name = match &self.machine_st.heap[s+1] {
|
||||
&HeapCellValue::Atom(ref name, _) =>
|
||||
name.clone(),
|
||||
_ =>
|
||||
unreachable!()
|
||||
};
|
||||
|
||||
let arity = match &self.machine_st.heap[s+2] {
|
||||
&HeapCellValue::Integer(ref arity) =>
|
||||
arity.to_usize().unwrap(),
|
||||
_ =>
|
||||
unreachable!()
|
||||
};
|
||||
let arity = match &self.machine_st.heap[s+2] {
|
||||
&HeapCellValue::Integer(ref arity) =>
|
||||
arity.to_usize().unwrap(),
|
||||
&HeapCellValue::Addr(Addr::Fixnum(n)) =>
|
||||
usize::try_from(n).unwrap(),
|
||||
_ =>
|
||||
unreachable!()
|
||||
};
|
||||
|
||||
exports.push(ModuleExport::PredicateKey((name, arity)));
|
||||
exports.push(ModuleExport::PredicateKey((name, arity)));
|
||||
}
|
||||
HeapCellValue::NamedStr(arity, ref name, _)
|
||||
if *arity == 3 && name.as_str() == "op" => {
|
||||
let name = match &self.machine_st.heap[s+3] {
|
||||
&HeapCellValue::Atom(ref name, _) =>
|
||||
name.clone(),
|
||||
_ =>
|
||||
unreachable!()
|
||||
};
|
||||
&HeapCellValue::Atom(ref name, _) =>
|
||||
name.clone(),
|
||||
_ =>
|
||||
unreachable!()
|
||||
};
|
||||
|
||||
let spec = match &self.machine_st.heap[s+2] {
|
||||
&HeapCellValue::Atom(ref name, _) =>
|
||||
name.clone(),
|
||||
_ =>
|
||||
unreachable!()
|
||||
};
|
||||
&HeapCellValue::Atom(ref name, _) =>
|
||||
name.clone(),
|
||||
_ =>
|
||||
unreachable!()
|
||||
};
|
||||
|
||||
let prec = match &self.machine_st.heap[s+1] {
|
||||
&HeapCellValue::Integer(ref arity) =>
|
||||
arity.to_usize().unwrap(),
|
||||
_ =>
|
||||
unreachable!()
|
||||
};
|
||||
let prec = match &self.machine_st.heap[s+1] {
|
||||
&HeapCellValue::Integer(ref arity) =>
|
||||
arity.to_usize().unwrap(),
|
||||
&HeapCellValue::Addr(Addr::Fixnum(n)) =>
|
||||
usize::try_from(n).unwrap(),
|
||||
_ =>
|
||||
unreachable!()
|
||||
};
|
||||
|
||||
exports.push(ModuleExport::OpDecl(to_op_decl(
|
||||
prec,
|
||||
@@ -595,47 +600,47 @@ impl Machine {
|
||||
}
|
||||
_ => unreachable!()
|
||||
}
|
||||
}
|
||||
_ => unreachable!()
|
||||
}
|
||||
_ => unreachable!()
|
||||
}
|
||||
|
||||
export_list = self.machine_st.heap[l+1].as_addr(l+1);
|
||||
}
|
||||
|
||||
export_list = self.machine_st.heap[l+1].as_addr(l+1);
|
||||
}
|
||||
|
||||
Ok(exports)
|
||||
Ok(exports)
|
||||
}
|
||||
|
||||
fn use_module<ToSource>(&mut self, to_src: ToSource)
|
||||
where ToSource: Fn(ClauseName) -> ModuleSource
|
||||
{
|
||||
// the term expander will overwrite the cached query, so save it here.
|
||||
let cached_query = mem::replace(&mut self.code_repo.cached_query, vec![]);
|
||||
// the term expander will overwrite the cached query, so save it here.
|
||||
let cached_query = mem::replace(&mut self.code_repo.cached_query, vec![]);
|
||||
|
||||
let module_spec = self.machine_st[temp_v!(1)].clone();
|
||||
let name = {
|
||||
let module_spec = self.machine_st[temp_v!(1)].clone();
|
||||
let name = {
|
||||
let addr = self.machine_st.store(self.machine_st.deref(module_spec));
|
||||
|
||||
match self.machine_st.heap.index_addr(&addr).as_ref() {
|
||||
HeapCellValue::Atom(name, _) => name.clone(),
|
||||
_ => unreachable!(),
|
||||
_ => unreachable!(),
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
let load_result = match to_src(name) {
|
||||
ModuleSource::Library(name) =>
|
||||
let load_result = match to_src(name) {
|
||||
ModuleSource::Library(name) =>
|
||||
if let Some(module) = self.indices.take_module(name.clone()) {
|
||||
self.indices.remove_module(clause_name!("user"), &module);
|
||||
self.indices.modules.insert(name.clone(), module);
|
||||
|
||||
Ok(name)
|
||||
} else {
|
||||
load_library(self, name, false)
|
||||
},
|
||||
ModuleSource::File(name) =>
|
||||
Ok(name)
|
||||
} else {
|
||||
load_library(self, name, false)
|
||||
},
|
||||
ModuleSource::File(name) =>
|
||||
load_module_from_file(self, PathBuf::from(name.as_str()), false)
|
||||
};
|
||||
};
|
||||
|
||||
let result = load_result.and_then(|name| {
|
||||
let result = load_result.and_then(|name| {
|
||||
let module = self.indices.take_module(name.clone()).unwrap();
|
||||
|
||||
if !module.is_impromptu_module {
|
||||
@@ -645,30 +650,30 @@ impl Machine {
|
||||
Ok(self.indices.insert_module(module))
|
||||
});
|
||||
|
||||
self.code_repo.cached_query = cached_query;
|
||||
self.code_repo.cached_query = cached_query;
|
||||
|
||||
if let Err(e) = result {
|
||||
self.throw_session_error(e, (clause_name!("use_module"), 1));
|
||||
}
|
||||
if let Err(e) = result {
|
||||
self.throw_session_error(e, (clause_name!("use_module"), 1));
|
||||
}
|
||||
}
|
||||
|
||||
fn use_qualified_module<ToSource>(&mut self, to_src: ToSource)
|
||||
where ToSource: Fn(ClauseName) -> ModuleSource
|
||||
{
|
||||
// the term expander will overwrite the cached query, so save it here.
|
||||
let cached_query = mem::replace(&mut self.code_repo.cached_query, vec![]);
|
||||
// the term expander will overwrite the cached query, so save it here.
|
||||
let cached_query = mem::replace(&mut self.code_repo.cached_query, vec![]);
|
||||
|
||||
let module_spec = self.machine_st[temp_v!(1)].clone();
|
||||
let name = {
|
||||
let module_spec = self.machine_st[temp_v!(1)].clone();
|
||||
let name = {
|
||||
let addr = self.machine_st.store(self.machine_st.deref(module_spec));
|
||||
|
||||
match self.machine_st.heap.index_addr(&addr).as_ref() {
|
||||
HeapCellValue::Atom(name, _) => name.clone(),
|
||||
_ => unreachable!(),
|
||||
_ => unreachable!(),
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
let exports = match self.extract_module_export_list() {
|
||||
let exports = match self.extract_module_export_list() {
|
||||
Ok(exports) => exports,
|
||||
Err(e) => {
|
||||
self.throw_session_error(SessionError::from(e), (clause_name!("use_module"), 2));
|
||||
@@ -676,38 +681,38 @@ impl Machine {
|
||||
}
|
||||
};
|
||||
|
||||
let load_result = match to_src(name) {
|
||||
ModuleSource::Library(name) =>
|
||||
let load_result = match to_src(name) {
|
||||
ModuleSource::Library(name) =>
|
||||
if let Some(module) = self.indices.take_module(name.clone()) {
|
||||
self.indices.remove_module(clause_name!("user"), &module);
|
||||
self.indices.modules.insert(name.clone(), module);
|
||||
|
||||
Ok(name)
|
||||
} else {
|
||||
load_library(self, name, false)
|
||||
},
|
||||
ModuleSource::File(name) =>
|
||||
Ok(name)
|
||||
} else {
|
||||
load_library(self, name, false)
|
||||
},
|
||||
ModuleSource::File(name) =>
|
||||
load_module_from_file(self, PathBuf::from(name.as_str()), false)
|
||||
};
|
||||
};
|
||||
|
||||
let result = load_result.and_then(|name| {
|
||||
let module = self.indices.take_module(name.clone()).unwrap();
|
||||
let result = load_result.and_then(|name| {
|
||||
let module = self.indices.take_module(name.clone()).unwrap();
|
||||
|
||||
if !module.is_impromptu_module {
|
||||
self.indices.use_qualified_module(&mut self.code_repo,
|
||||
self.machine_st.flags,
|
||||
&module,
|
||||
&exports)?;
|
||||
self.indices.use_qualified_module(&mut self.code_repo,
|
||||
self.machine_st.flags,
|
||||
&module,
|
||||
&exports)?;
|
||||
}
|
||||
|
||||
Ok(self.indices.insert_module(module))
|
||||
Ok(self.indices.insert_module(module))
|
||||
});
|
||||
|
||||
self.code_repo.cached_query = cached_query;
|
||||
self.code_repo.cached_query = cached_query;
|
||||
|
||||
if let Err(e) = result {
|
||||
self.throw_session_error(e, (clause_name!("use_module"), 2));
|
||||
}
|
||||
if let Err(e) = result {
|
||||
self.throw_session_error(e, (clause_name!("use_module"), 2));
|
||||
}
|
||||
}
|
||||
|
||||
fn handle_toplevel_command(&mut self, code_ptr: REPLCodePtr, p: LocalCodePtr) {
|
||||
@@ -722,14 +727,14 @@ impl Machine {
|
||||
self.throw_session_error(e, (clause_name!("repl"), 0));
|
||||
}
|
||||
}
|
||||
REPLCodePtr::UseModule =>
|
||||
self.use_module(ModuleSource::Library),
|
||||
REPLCodePtr::UseModuleFromFile =>
|
||||
self.use_module(ModuleSource::File),
|
||||
REPLCodePtr::UseQualifiedModule =>
|
||||
self.use_qualified_module(ModuleSource::Library),
|
||||
REPLCodePtr::UseQualifiedModuleFromFile =>
|
||||
self.use_qualified_module(ModuleSource::File)
|
||||
REPLCodePtr::UseModule =>
|
||||
self.use_module(ModuleSource::Library),
|
||||
REPLCodePtr::UseModuleFromFile =>
|
||||
self.use_module(ModuleSource::File),
|
||||
REPLCodePtr::UseQualifiedModule =>
|
||||
self.use_qualified_module(ModuleSource::Library),
|
||||
REPLCodePtr::UseQualifiedModuleFromFile =>
|
||||
self.use_qualified_module(ModuleSource::File)
|
||||
}
|
||||
|
||||
self.machine_st.p = CodePtr::Local(p);
|
||||
@@ -786,7 +791,7 @@ impl Machine {
|
||||
}
|
||||
|
||||
pub(super) fn run_query(&mut self) {
|
||||
self.machine_st.cp = LocalCodePtr::TopLevel(0, self.code_repo.size_of_cached_query());
|
||||
self.machine_st.cp = LocalCodePtr::TopLevel(0, self.code_repo.size_of_cached_query());
|
||||
let end_ptr = CodePtr::Local(self.machine_st.cp);
|
||||
|
||||
while self.machine_st.p < end_ptr {
|
||||
|
||||
@@ -23,9 +23,9 @@ use crate::ref_thread_local::RefThreadLocal;
|
||||
use indexmap::{IndexMap, IndexSet};
|
||||
|
||||
use std::cmp;
|
||||
use std::convert::TryFrom;
|
||||
use std::io::{stdout, Write};
|
||||
use std::iter::once;
|
||||
use std::mem;
|
||||
use std::rc::Rc;
|
||||
|
||||
use crate::crossterm::event::{read, Event, KeyCode, KeyEvent};
|
||||
@@ -269,9 +269,9 @@ impl MachineState {
|
||||
}
|
||||
}
|
||||
|
||||
fn skip_max_list_result(&mut self, max_steps: &Integer) {
|
||||
fn skip_max_list_result(&mut self, max_steps: Option<isize>) {
|
||||
let search_result =
|
||||
if let Some(max_steps) = max_steps.to_isize() {
|
||||
if let Some(max_steps) = max_steps {
|
||||
if max_steps == -1 {
|
||||
self.detect_cycles(self[temp_v!(3)])
|
||||
} else {
|
||||
@@ -307,59 +307,66 @@ impl MachineState {
|
||||
};
|
||||
}
|
||||
|
||||
pub(super) fn skip_max_list(&mut self) -> CallResult {
|
||||
pub(super)
|
||||
fn skip_max_list(&mut self) -> CallResult {
|
||||
let max_steps = self.store(self.deref(self[temp_v!(2)]));
|
||||
|
||||
match max_steps {
|
||||
Addr::Con(h) if self.heap.integer_at(h) => {
|
||||
if let HeapCellValue::Integer(ref max_steps) = self.heap.clone(h) {
|
||||
if max_steps.to_isize().map(|i| i >= -1).unwrap_or(false) {
|
||||
let n = self.store(self.deref(self[temp_v!(1)]));
|
||||
|
||||
match n {
|
||||
Addr::Con(h) if self.heap.integer_at(h) => {
|
||||
if let HeapCellValue::Integer(ref n) = &self.heap[h] {
|
||||
if n.as_ref() == &0 {
|
||||
let xs0 = self[temp_v!(3)];
|
||||
let xs = self[temp_v!(4)];
|
||||
|
||||
self.unify(xs0, xs);
|
||||
} else {
|
||||
self.skip_max_list_result(max_steps.as_ref());
|
||||
}
|
||||
} else {
|
||||
unreachable!()
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
self.skip_max_list_result(max_steps.as_ref());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
self.fail = true;
|
||||
}
|
||||
} else {
|
||||
unreachable!()
|
||||
}
|
||||
}
|
||||
Addr::HeapCell(_) | Addr::StackCell(..) => {
|
||||
Addr::HeapCell(_) | Addr::StackCell(..) | Addr::AttrVar(_) => {
|
||||
let stub = MachineError::functor_stub(clause_name!("$skip_max_list"), 4);
|
||||
return Err(self.error_form(MachineError::instantiation_error(), stub));
|
||||
}
|
||||
addr => {
|
||||
let stub = MachineError::functor_stub(clause_name!("$skip_max_list"), 4);
|
||||
return Err(
|
||||
self.error_form(
|
||||
MachineError::type_error(
|
||||
self.heap.h(),
|
||||
ValidType::Integer,
|
||||
addr
|
||||
),
|
||||
stub,
|
||||
)
|
||||
);
|
||||
let max_steps_n =
|
||||
match Number::try_from((max_steps, &self.heap)) {
|
||||
Ok(Number::Integer(n)) => n.to_isize(),
|
||||
Ok(Number::Fixnum(n)) => Some(n),
|
||||
_ => None,
|
||||
};
|
||||
|
||||
if max_steps_n.map(|i| i >= -1).unwrap_or(false) {
|
||||
let n = self.store(self.deref(self[temp_v!(1)]));
|
||||
|
||||
match Number::try_from((n, &self.heap)) {
|
||||
Ok(Number::Integer(n)) => {
|
||||
if n.as_ref() == &0 {
|
||||
let xs0 = self[temp_v!(3)];
|
||||
let xs = self[temp_v!(4)];
|
||||
|
||||
self.unify(xs0, xs);
|
||||
} else {
|
||||
self.skip_max_list_result(max_steps_n);
|
||||
}
|
||||
}
|
||||
Ok(Number::Fixnum(n)) => {
|
||||
if n == 0 {
|
||||
let xs0 = self[temp_v!(3)];
|
||||
let xs = self[temp_v!(4)];
|
||||
|
||||
self.unify(xs0, xs);
|
||||
} else {
|
||||
self.skip_max_list_result(max_steps_n);
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
self.skip_max_list_result(max_steps_n);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
let stub = MachineError::functor_stub(clause_name!("$skip_max_list"), 4);
|
||||
return Err(
|
||||
self.error_form(
|
||||
MachineError::type_error(
|
||||
self.heap.h(),
|
||||
ValidType::Integer,
|
||||
addr
|
||||
),
|
||||
stub,
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@@ -671,6 +678,10 @@ impl MachineState {
|
||||
let addr = self.heap.put_constant(Constant::Integer(n));
|
||||
self.unify(nx, addr);
|
||||
}
|
||||
Ok(Term::Constant(_, Constant::Fixnum(n))) => {
|
||||
let addr = self.heap.put_constant(Constant::Fixnum(n));
|
||||
self.unify(nx, addr);
|
||||
}
|
||||
Ok(Term::Constant(_, Constant::CharCode(c))) => {
|
||||
self.unify(nx, Addr::CharCode(c))
|
||||
}
|
||||
@@ -774,17 +785,18 @@ impl MachineState {
|
||||
}
|
||||
&SystemClauseType::BindFromRegister => {
|
||||
let reg = self.store(self.deref(self[temp_v!(2)]));
|
||||
let n = match reg {
|
||||
Addr::Con(h) =>
|
||||
if let HeapCellValue::Integer(ref n) = &self.heap[h] {
|
||||
let n =
|
||||
match Number::try_from((reg, &self.heap)) {
|
||||
Ok(Number::Integer(n)) => {
|
||||
n.to_usize()
|
||||
} else {
|
||||
}
|
||||
Ok(Number::Fixnum(n)) => {
|
||||
usize::try_from(n).ok()
|
||||
}
|
||||
_ => {
|
||||
unreachable!()
|
||||
}
|
||||
_ => {
|
||||
unreachable!()
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
if let Some(n) = n {
|
||||
if n <= MAX_ARITY {
|
||||
@@ -1020,15 +1032,36 @@ impl MachineState {
|
||||
let mut chars = String::new();
|
||||
|
||||
for addr in addrs {
|
||||
match addr {
|
||||
Addr::Con(h) if self.heap.integer_at(h) => {
|
||||
if let HeapCellValue::Integer(ref n) = &self.heap[h] {
|
||||
let c = self.int_to_char_code(&n, "atom_codes", 2)?;
|
||||
chars.push(std::char::from_u32(c).unwrap());
|
||||
} else {
|
||||
unreachable!()
|
||||
match Number::try_from((addr, &self.heap)) {
|
||||
Ok(Number::Fixnum(n)) => {
|
||||
match u32::try_from(n) {
|
||||
Ok(c) => {
|
||||
chars.push(std::char::from_u32(c).unwrap());
|
||||
}
|
||||
_ => {
|
||||
let c = self.int_to_char_code(
|
||||
&Integer::from(n),
|
||||
"atom_codes",
|
||||
2,
|
||||
)?;
|
||||
|
||||
chars.push(std::char::from_u32(c).unwrap());
|
||||
}
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
Ok(Number::Integer(n)) => {
|
||||
let c = self.int_to_char_code(&n, "atom_codes", 2)?;
|
||||
chars.push(std::char::from_u32(c).unwrap());
|
||||
|
||||
continue;
|
||||
}
|
||||
_ => {
|
||||
}
|
||||
}
|
||||
|
||||
match addr {
|
||||
Addr::CharCode(c) => {
|
||||
chars.push(std::char::from_u32(c).unwrap());
|
||||
}
|
||||
@@ -1056,7 +1089,9 @@ impl MachineState {
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => unreachable!(),
|
||||
_ => {
|
||||
unreachable!()
|
||||
}
|
||||
};
|
||||
}
|
||||
&SystemClauseType::AtomLength => {
|
||||
@@ -1088,17 +1123,6 @@ impl MachineState {
|
||||
|
||||
self.unify(a2, len);
|
||||
}
|
||||
&SystemClauseType::CallAttributeGoals => {
|
||||
let p = self.attr_var_init.project_attrs_loc;
|
||||
|
||||
if self.last_call {
|
||||
self.execute_at_index(2, dir_entry!(p));
|
||||
} else {
|
||||
self.call_at_index(2, dir_entry!(p));
|
||||
}
|
||||
|
||||
return Ok(());
|
||||
}
|
||||
&SystemClauseType::CallContinuation => {
|
||||
let stub = MachineError::functor_stub(clause_name!("call_continuation"), 1);
|
||||
|
||||
@@ -1201,21 +1225,23 @@ impl MachineState {
|
||||
let n = self[temp_v!(1)];
|
||||
let chs = self[temp_v!(2)];
|
||||
|
||||
let string = match self.store(self.deref(n)) {
|
||||
Addr::Float(OrderedFloat(n)) => {
|
||||
format!("{0:<20?}", n)
|
||||
}
|
||||
Addr::Con(h) if self.heap.integer_at(h) => {
|
||||
if let HeapCellValue::Integer(ref n) = &self.heap[h] {
|
||||
let n = self.store(self.deref(n));
|
||||
|
||||
let string =
|
||||
match Number::try_from((n, &self.heap)) {
|
||||
Ok(Number::Float(OrderedFloat(n))) => {
|
||||
format!("{0:<20?}", n)
|
||||
}
|
||||
Ok(Number::Fixnum(n)) => {
|
||||
n.to_string()
|
||||
} else {
|
||||
}
|
||||
Ok(Number::Integer(n)) => {
|
||||
n.to_string()
|
||||
}
|
||||
_ => {
|
||||
unreachable!()
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
unreachable!()
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
let chars = string.trim().chars().map(|c| Addr::Char(c));
|
||||
let char_list = Addr::HeapCell(self.heap.to_list(chars));
|
||||
@@ -1226,21 +1252,21 @@ impl MachineState {
|
||||
let n = self[temp_v!(1)];
|
||||
let chs = self[temp_v!(2)];
|
||||
|
||||
let string = match self.store(self.deref(n)) {
|
||||
Addr::Float(OrderedFloat(n)) => {
|
||||
format!("{0:<20?}", n)
|
||||
}
|
||||
Addr::Con(h) if self.heap.integer_at(h) => {
|
||||
if let HeapCellValue::Integer(ref n) = &self.heap[h] {
|
||||
let string =
|
||||
match Number::try_from((n, &self.heap)) {
|
||||
Ok(Number::Float(OrderedFloat(n))) => {
|
||||
format!("{0:<20?}", n)
|
||||
}
|
||||
Ok(Number::Fixnum(n)) => {
|
||||
n.to_string()
|
||||
} else {
|
||||
}
|
||||
Ok(Number::Integer(n)) => {
|
||||
n.to_string()
|
||||
}
|
||||
_ => {
|
||||
unreachable!()
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
unreachable!()
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
let codes = string
|
||||
.trim()
|
||||
@@ -1322,33 +1348,37 @@ impl MachineState {
|
||||
}
|
||||
addr if addr.is_ref() => {
|
||||
let a2 = self[temp_v!(2)];
|
||||
let a2 = self.store(self.deref(a2));
|
||||
|
||||
match self.store(self.deref(a2)) {
|
||||
Addr::CharCode(code) => {
|
||||
if let Some(c) = std::char::from_u32(code) {
|
||||
self.unify(Addr::Char(c), addr);
|
||||
} else {
|
||||
self.fail = true;
|
||||
let c = match Number::try_from((a2, &self.heap)) {
|
||||
Ok(Number::Integer(n)) => {
|
||||
self.int_to_char_code(&n, "char_code", 2)?
|
||||
}
|
||||
Ok(Number::Fixnum(n)) => {
|
||||
self.int_to_char_code(&Integer::from(n), "char_code", 2)?
|
||||
}
|
||||
_ => {
|
||||
match addr {
|
||||
Addr::CharCode(c) => {
|
||||
c
|
||||
}
|
||||
_ => {
|
||||
self.fail = true;
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
}
|
||||
Addr::Con(h) if self.heap.integer_at(h) => {
|
||||
let c =
|
||||
if let HeapCellValue::Integer(n) = &self.heap[h] {
|
||||
self.int_to_char_code(&n, "char_code", 2)?
|
||||
} else {
|
||||
unreachable!()
|
||||
};
|
||||
|
||||
if let Some(c) = std::char::from_u32(c) {
|
||||
self.unify(Addr::Char(c), addr);
|
||||
} else {
|
||||
self.fail = true;
|
||||
}
|
||||
}
|
||||
_ => self.fail = true,
|
||||
};
|
||||
|
||||
if let Some(c) = std::char::from_u32(c) {
|
||||
self.unify(Addr::Char(c), addr);
|
||||
} else {
|
||||
self.fail = true;
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
unreachable!();
|
||||
}
|
||||
_ => unreachable!(),
|
||||
};
|
||||
}
|
||||
&SystemClauseType::CheckCutPoint => {
|
||||
@@ -1967,16 +1997,20 @@ impl MachineState {
|
||||
let specifier = self[temp_v!(2)];
|
||||
let op = self[temp_v!(3)];
|
||||
|
||||
let priority = match self.store(self.deref(priority)) {
|
||||
Addr::Con(h) if self.heap.integer_at(h) =>
|
||||
if let HeapCellValue::Integer(ref n) = &self.heap[h] {
|
||||
let priority = self.store(self.deref(priority));
|
||||
|
||||
let priority =
|
||||
match Number::try_from((priority, &self.heap)) {
|
||||
Ok(Number::Integer(n)) => {
|
||||
n.to_usize().unwrap()
|
||||
} else {
|
||||
unreachable!()
|
||||
},
|
||||
_ =>
|
||||
unreachable!(),
|
||||
};
|
||||
}
|
||||
Ok(Number::Fixnum(n)) => {
|
||||
usize::try_from(n).unwrap()
|
||||
}
|
||||
_ => {
|
||||
unreachable!();
|
||||
}
|
||||
};
|
||||
|
||||
let specifier = match self.store(self.deref(specifier)) {
|
||||
Addr::Con(h) if self.heap.atom_at(h) =>
|
||||
@@ -2041,10 +2075,6 @@ impl MachineState {
|
||||
let attr_goals = self.attr_var_init.attribute_goals.clone();
|
||||
self.fetch_attribute_goals(attr_goals);
|
||||
}
|
||||
&SystemClauseType::FetchAttributeGoals => {
|
||||
let attr_goals = mem::replace(&mut self.attr_var_init.attribute_goals, vec![]);
|
||||
self.fetch_attribute_goals(attr_goals);
|
||||
}
|
||||
&SystemClauseType::GetAttributedVariableList => {
|
||||
let attr_var = self.store(self.deref(self[temp_v!(1)]));
|
||||
let attr_var_list =
|
||||
@@ -2080,35 +2110,36 @@ impl MachineState {
|
||||
}
|
||||
&SystemClauseType::GetAttrVarQueueBeyond => {
|
||||
let addr = self[temp_v!(1)];
|
||||
let addr = self.store(self.deref(addr));
|
||||
|
||||
match self.store(self.deref(addr)) {
|
||||
Addr::Usize(b) => {
|
||||
let iter = self.gather_attr_vars_created_since(b);
|
||||
|
||||
let var_list_addr = Addr::HeapCell(self.heap.to_list(iter));
|
||||
let list_addr = self[temp_v!(2)];
|
||||
|
||||
self.unify(var_list_addr, list_addr);
|
||||
}
|
||||
Addr::Con(h) if self.heap.integer_at(h) => {
|
||||
if let HeapCellValue::Integer(n) = self.heap.clone(h) {
|
||||
if let Some(b) = n.to_usize() {
|
||||
let iter = self.gather_attr_vars_created_since(b);
|
||||
|
||||
let var_list_addr = Addr::HeapCell(self.heap.to_list(iter));
|
||||
let list_addr = self[temp_v!(2)];
|
||||
|
||||
self.unify(var_list_addr, list_addr);
|
||||
} else {
|
||||
self.fail = true;
|
||||
}
|
||||
} else {
|
||||
unreachable!()
|
||||
let b =
|
||||
match addr {
|
||||
Addr::Usize(b) => {
|
||||
Some(b)
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
self.fail = true;
|
||||
}
|
||||
_ => {
|
||||
match Number::try_from((addr, &self.heap)) {
|
||||
Ok(Number::Integer(n)) => {
|
||||
n.to_usize()
|
||||
}
|
||||
Ok(Number::Fixnum(n)) => {
|
||||
usize::try_from(n).ok()
|
||||
}
|
||||
_ => {
|
||||
self.fail = true;
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
if let Some(b) = b {
|
||||
let iter = self.gather_attr_vars_created_since(b);
|
||||
|
||||
let var_list_addr = Addr::HeapCell(self.heap.to_list(iter));
|
||||
let list_addr = self[temp_v!(2)];
|
||||
|
||||
self.unify(var_list_addr, list_addr);
|
||||
}
|
||||
}
|
||||
&SystemClauseType::GetContinuationChunk => {
|
||||
@@ -2327,51 +2358,58 @@ impl MachineState {
|
||||
CWILCallPolicy::new_in_place(call_policy);
|
||||
}
|
||||
|
||||
match (a1, a2) {
|
||||
(Addr::Usize(bp), Addr::Con(h))
|
||||
| (Addr::CutPoint(bp), Addr::Con(h))
|
||||
if self.heap.integer_at(h) => {
|
||||
if let HeapCellValue::Integer(n) = self.heap.clone(h) {
|
||||
match call_policy.downcast_mut::<CWILCallPolicy>().ok() {
|
||||
Some(call_policy) => {
|
||||
let count = call_policy.add_limit(Integer::from(&*n), bp);
|
||||
let count = self.heap.to_unifiable(
|
||||
HeapCellValue::Integer(Rc::new(count.clone()))
|
||||
);
|
||||
let n =
|
||||
match Number::try_from((a2, &self.heap)) {
|
||||
Ok(Number::Integer(n)) => {
|
||||
Integer::from(&*n.clone())
|
||||
}
|
||||
Ok(Number::Fixnum(n)) => {
|
||||
Integer::from(n)
|
||||
}
|
||||
_ => {
|
||||
let stub = MachineError::functor_stub(
|
||||
clause_name!("call_with_inference_limit"),
|
||||
3,
|
||||
);
|
||||
|
||||
let a3 = self[temp_v!(3)];
|
||||
let type_error = self.error_form(
|
||||
MachineError::type_error(
|
||||
self.heap.h(),
|
||||
ValidType::Integer,
|
||||
a2,
|
||||
),
|
||||
stub,
|
||||
);
|
||||
|
||||
self.unify(a3, count);
|
||||
}
|
||||
None => {
|
||||
panic!(
|
||||
"install_inference_counter: should have installed \\
|
||||
CWILCallPolicy."
|
||||
)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
unreachable!()
|
||||
self.throw_exception(type_error);
|
||||
return Ok(());
|
||||
}
|
||||
};
|
||||
|
||||
match a1 {
|
||||
Addr::Usize(bp) | Addr::CutPoint(bp) => {
|
||||
match call_policy.downcast_mut::<CWILCallPolicy>().ok() {
|
||||
Some(call_policy) => {
|
||||
let count = call_policy.add_limit(n, bp).clone();
|
||||
let count = self.heap.to_unifiable(
|
||||
HeapCellValue::Integer(Rc::new(count))
|
||||
);
|
||||
|
||||
let a3 = self[temp_v!(3)];
|
||||
self.unify(a3, count);
|
||||
}
|
||||
None => {
|
||||
panic!(
|
||||
"install_inference_counter: should have installed \\
|
||||
CWILCallPolicy."
|
||||
)
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
let stub = MachineError::functor_stub(
|
||||
clause_name!("call_with_inference_limit"),
|
||||
3,
|
||||
);
|
||||
|
||||
let type_error = self.error_form(
|
||||
MachineError::type_error(
|
||||
self.heap.h(),
|
||||
ValidType::Integer,
|
||||
a2,
|
||||
),
|
||||
stub,
|
||||
);
|
||||
|
||||
self.throw_exception(type_error)
|
||||
}
|
||||
};
|
||||
_ => {
|
||||
unreachable!();
|
||||
}
|
||||
}
|
||||
}
|
||||
&SystemClauseType::ModuleExists => {
|
||||
let module = self.store(self.deref(self[temp_v!(1)]));
|
||||
@@ -2582,9 +2620,9 @@ impl MachineState {
|
||||
|
||||
match a1 {
|
||||
Addr::Usize(bp) | Addr::CutPoint(bp) => {
|
||||
let count = call_policy.remove_limit(bp);
|
||||
let count = call_policy.remove_limit(bp).clone();
|
||||
let count = self.heap.to_unifiable(
|
||||
HeapCellValue::Integer(Rc::new(count.clone())),
|
||||
HeapCellValue::Integer(Rc::new(count)),
|
||||
);
|
||||
|
||||
let a2 = self[temp_v!(2)];
|
||||
@@ -3029,29 +3067,24 @@ impl MachineState {
|
||||
Addr::CharCode(c) => {
|
||||
Integer::from(c)
|
||||
}
|
||||
Addr::Con(h) if self.heap.integer_at(h) => {
|
||||
if let HeapCellValue::Integer(ref n) = &self.heap[h] {
|
||||
Integer::from(&**n)
|
||||
} else {
|
||||
unreachable!()
|
||||
}
|
||||
}
|
||||
Addr::Con(h) if self.heap.rational_at(h) => {
|
||||
if let HeapCellValue::Rational(r) = &self.heap[h] {
|
||||
if r.denom() == &1 {
|
||||
r.numer().clone()
|
||||
} else {
|
||||
_ => {
|
||||
match Number::try_from((seed, &self.heap)) {
|
||||
Ok(Number::Fixnum(n)) => {
|
||||
Integer::from(n)
|
||||
}
|
||||
Ok(Number::Integer(n)) => {
|
||||
Integer::from(n.as_ref())
|
||||
}
|
||||
Ok(Number::Rational(n))
|
||||
if n.denom() == &1 => {
|
||||
n.numer().clone()
|
||||
}
|
||||
_ => {
|
||||
self.fail = true;
|
||||
return Ok(());
|
||||
}
|
||||
} else {
|
||||
unreachable!()
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
self.fail = true;
|
||||
return Ok(());
|
||||
}
|
||||
};
|
||||
|
||||
let mut rand = RANDOM_STATE.borrow_mut();
|
||||
@@ -3195,43 +3228,33 @@ impl MachineState {
|
||||
}
|
||||
};
|
||||
|
||||
let arity = match self.store(self.deref(arity)) {
|
||||
Addr::Con(h) if self.heap.integer_at(h) => {
|
||||
if let HeapCellValue::Integer(ref n) = &self.heap[h] {
|
||||
n.clone()
|
||||
} else {
|
||||
let arity = self.store(self.deref(arity));
|
||||
|
||||
let arity =
|
||||
match Number::try_from((arity, &self.heap)) {
|
||||
Ok(Number::Fixnum(n)) => {
|
||||
Integer::from(n)
|
||||
}
|
||||
Ok(Number::Integer(n)) => {
|
||||
Integer::from(n.as_ref())
|
||||
}
|
||||
_ => {
|
||||
unreachable!()
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
unreachable!()
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
let first_idx = match indices
|
||||
.code_dir
|
||||
.get(&(name.clone(), arity.to_usize().unwrap()))
|
||||
{
|
||||
Some(ref idx) => {
|
||||
Some(ref idx) if idx.local().is_some() => {
|
||||
if let Some(idx) = idx.local() {
|
||||
idx
|
||||
} else {
|
||||
let arity = arity.to_usize().unwrap();
|
||||
let stub = MachineError::functor_stub(name.clone(), arity);
|
||||
let h = self.heap.h();
|
||||
|
||||
let err = MachineError::existence_error(
|
||||
h,
|
||||
ExistenceError::Procedure(name, arity),
|
||||
);
|
||||
|
||||
let err = self.error_form(err, stub);
|
||||
|
||||
self.throw_exception(err);
|
||||
return Ok(());
|
||||
unreachable!()
|
||||
}
|
||||
}
|
||||
None => {
|
||||
_ => {
|
||||
let arity = arity.to_usize().unwrap();
|
||||
let stub = MachineError::functor_stub(name.clone(), arity);
|
||||
let h = self.heap.h();
|
||||
@@ -3279,7 +3302,7 @@ impl MachineState {
|
||||
let mut printer = HCPrinter::new(&self, &indices.op_dir, PrinterOutputter::new());
|
||||
|
||||
if let &Addr::Con(h) = &ignore_ops {
|
||||
if let HeapCellValue::Atom(ref name, _) = &self.heap[h] {
|
||||
if let HeapCellValue::Atom(ref name, _) = &self.heap[h] {
|
||||
printer.ignore_ops = name.as_str() == "true";
|
||||
} else {
|
||||
unreachable!()
|
||||
@@ -3287,7 +3310,7 @@ impl MachineState {
|
||||
}
|
||||
|
||||
if let &Addr::Con(h) = &numbervars {
|
||||
if let HeapCellValue::Atom(ref name, _) = &self.heap[h] {
|
||||
if let HeapCellValue::Atom(ref name, _) = &self.heap[h] {
|
||||
printer.numbervars = name.as_str() == "true";
|
||||
} else {
|
||||
unreachable!()
|
||||
@@ -3295,23 +3318,32 @@ impl MachineState {
|
||||
}
|
||||
|
||||
if let &Addr::Con(h) = "ed {
|
||||
if let HeapCellValue::Atom(ref name, _) = &self.heap[h] {
|
||||
if let HeapCellValue::Atom(ref name, _) = &self.heap[h] {
|
||||
printer.quoted = name.as_str() == "true";
|
||||
} else {
|
||||
unreachable!()
|
||||
}
|
||||
}
|
||||
|
||||
if let &Addr::Con(h) = &max_depth {
|
||||
if let HeapCellValue::Integer(ref n) = &self.heap[h] {
|
||||
match Number::try_from((max_depth, &self.heap)) {
|
||||
Ok(Number::Fixnum(n)) => {
|
||||
if let Ok(n) = usize::try_from(n) {
|
||||
printer.max_depth = n;
|
||||
} else {
|
||||
self.fail = true;
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
Ok(Number::Integer(n)) => {
|
||||
if let Some(n) = n.to_usize() {
|
||||
printer.max_depth = n;
|
||||
} else {
|
||||
self.fail = true;
|
||||
return Ok(());
|
||||
}
|
||||
} else {
|
||||
unreachable!()
|
||||
}
|
||||
_ => {
|
||||
unreachable!();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -362,7 +362,7 @@ impl MachineState {
|
||||
wam.code_repo.cached_query = code;
|
||||
|
||||
self.cp = LocalCodePtr::TopLevel(0, 0);
|
||||
|
||||
|
||||
self.at_end_of_expansion = false;
|
||||
self.flags.double_quotes = DoubleQuotes::Chars;
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@ use indexmap::{IndexMap, IndexSet};
|
||||
use std::borrow::BorrowMut;
|
||||
use std::cell::Cell;
|
||||
use std::collections::VecDeque;
|
||||
use std::convert::TryFrom;
|
||||
use std::mem;
|
||||
use std::ops::DerefMut;
|
||||
use std::rc::Rc;
|
||||
@@ -211,8 +212,8 @@ fn setup_op_decl(
|
||||
};
|
||||
|
||||
let prec = match *terms.pop().unwrap() {
|
||||
Term::Constant(_, Constant::Integer(bi)) => match bi.to_usize() {
|
||||
Some(n) if n <= 1200 => n,
|
||||
Term::Constant(_, Constant::Fixnum(bi)) => match usize::try_from(bi) {
|
||||
Ok(n) if n <= 1200 => n,
|
||||
_ => return Err(ParserError::InconsistentEntry),
|
||||
},
|
||||
_ => return Err(ParserError::InconsistentEntry),
|
||||
@@ -232,8 +233,13 @@ fn setup_predicate_indicator(term: &mut Term) -> Result<PredicateKey, ParserErro
|
||||
|
||||
let arity = arity
|
||||
.to_constant()
|
||||
.and_then(|c| c.to_integer())
|
||||
.and_then(|n| n.to_usize())
|
||||
.and_then(|c| {
|
||||
match c {
|
||||
Constant::Integer(n) => n.to_usize(),
|
||||
Constant::Fixnum(n) => usize::try_from(n).ok(),
|
||||
_ => None
|
||||
}
|
||||
})
|
||||
.ok_or(ParserError::InvalidModuleExport)?;
|
||||
|
||||
let name = name
|
||||
@@ -246,7 +252,7 @@ fn setup_predicate_indicator(term: &mut Term) -> Result<PredicateKey, ParserErro
|
||||
} else {
|
||||
Ok((name, arity + 2))
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => Err(ParserError::InvalidModuleExport),
|
||||
}
|
||||
}
|
||||
@@ -344,7 +350,7 @@ fn setup_use_module_decl(mut terms: Vec<Box<Term>>) -> Result<ModuleSource, Pars
|
||||
|
||||
fn setup_double_quotes(mut terms: Vec<Box<Term>>) -> Result<DoubleQuotes, ParserError> {
|
||||
let dbl_quotes = *terms.pop().unwrap();
|
||||
|
||||
|
||||
match terms[0].as_ref() {
|
||||
Term::Constant(_, Constant::Atom(ref name, _))
|
||||
if name.as_str() == "double_quotes" => {
|
||||
@@ -629,26 +635,26 @@ fn setup_declaration<'a, 'b, 'c>(
|
||||
|
||||
match term {
|
||||
Term::Clause(_, name, mut terms, _) =>
|
||||
match (name.as_str(), terms.len()) {
|
||||
("dynamic", 1) => {
|
||||
let (name, arity) = setup_predicate_indicator(&mut *terms.pop().unwrap())?;
|
||||
Ok(Declaration::Dynamic(name, arity))
|
||||
}
|
||||
("initialization", 1) => {
|
||||
let mut rel_worker = RelationWorker::new(flags, line_num, col_num);
|
||||
let query_terms = rel_worker.setup_query(indices, terms, false)?;
|
||||
let queue = rel_worker.parse_queue(indices)?;
|
||||
match (name.as_str(), terms.len()) {
|
||||
("dynamic", 1) => {
|
||||
let (name, arity) = setup_predicate_indicator(&mut *terms.pop().unwrap())?;
|
||||
Ok(Declaration::Dynamic(name, arity))
|
||||
}
|
||||
("initialization", 1) => {
|
||||
let mut rel_worker = RelationWorker::new(flags, line_num, col_num);
|
||||
let query_terms = rel_worker.setup_query(indices, terms, false)?;
|
||||
let queue = rel_worker.parse_queue(indices)?;
|
||||
|
||||
Ok(Declaration::ModuleInitialization(query_terms, queue))
|
||||
}
|
||||
("module", 2) =>
|
||||
Ok(Declaration::Module(setup_module_decl(terms, indices.atom_tbl())?)),
|
||||
("op", 3) =>
|
||||
Ok(Declaration::Op(setup_op_decl(terms, indices.atom_tbl())?)),
|
||||
("non_counted_backtracking", 1) => {
|
||||
let (name, arity) = setup_predicate_indicator(&mut *terms.pop().unwrap())?;
|
||||
Ok(Declaration::NonCountedBacktracking(name, arity))
|
||||
}
|
||||
Ok(Declaration::ModuleInitialization(query_terms, queue))
|
||||
}
|
||||
("module", 2) =>
|
||||
Ok(Declaration::Module(setup_module_decl(terms, indices.atom_tbl())?)),
|
||||
("op", 3) =>
|
||||
Ok(Declaration::Op(setup_op_decl(terms, indices.atom_tbl())?)),
|
||||
("non_counted_backtracking", 1) => {
|
||||
let (name, arity) = setup_predicate_indicator(&mut *terms.pop().unwrap())?;
|
||||
Ok(Declaration::NonCountedBacktracking(name, arity))
|
||||
}
|
||||
("set_prolog_flag", 2) => {
|
||||
Ok(Declaration::SetPrologFlag(setup_double_quotes(terms)?))
|
||||
}
|
||||
@@ -656,27 +662,31 @@ fn setup_declaration<'a, 'b, 'c>(
|
||||
let mut term = *terms.pop().unwrap();
|
||||
|
||||
match setup_predicate_indicator(&mut term) {
|
||||
Ok((name, arity)) =>
|
||||
Ok(Declaration::MultiFile(MultiFileIndicator::LocalScoped(name, arity))),
|
||||
_ =>
|
||||
Ok((name, arity)) => {
|
||||
Ok(Declaration::MultiFile(MultiFileIndicator::LocalScoped(name, arity)))
|
||||
}
|
||||
_ => {
|
||||
setup_scoped_predicate_indicator(&mut term)
|
||||
.map(|key| {
|
||||
Declaration::MultiFile(MultiFileIndicator::ModuleScoped(key))
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
("use_module", 1) => {
|
||||
Ok(Declaration::UseModule(setup_use_module_decl(terms)?))
|
||||
("use_module", 1) => {
|
||||
Ok(Declaration::UseModule(setup_use_module_decl(terms)?))
|
||||
}
|
||||
("use_module", 2) => {
|
||||
let (name, exports) = setup_qualified_import(terms, indices.atom_tbl())?;
|
||||
Ok(Declaration::UseQualifiedModule(name, exports))
|
||||
}
|
||||
_ => {
|
||||
Err(ParserError::InconsistentEntry)
|
||||
("use_module", 2) => {
|
||||
let (name, exports) = setup_qualified_import(terms, indices.atom_tbl())?;
|
||||
Ok(Declaration::UseQualifiedModule(name, exports))
|
||||
}
|
||||
_ => {
|
||||
Err(ParserError::InconsistentEntry)
|
||||
}
|
||||
},
|
||||
_ => Err(ParserError::InconsistentEntry),
|
||||
},
|
||||
_ => {
|
||||
Err(ParserError::InconsistentEntry)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1249,7 +1259,7 @@ impl<'a> TopLevelBatchWorker<'a> {
|
||||
|
||||
while !self.term_stream.eof()? {
|
||||
let term = self.term_stream.read_term(&indices.op_dir)?;
|
||||
|
||||
|
||||
// if is_consistent is false, preds is non-empty.
|
||||
let term = if !term.is_consistent(&preds) {
|
||||
self.process_result(indices, &mut preds)?;
|
||||
|
||||
Reference in New Issue
Block a user