initial commit for merge
This commit is contained in:
6
Cargo.lock
generated
6
Cargo.lock
generated
@@ -444,8 +444,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "prolog_parser"
|
name = "prolog_parser"
|
||||||
version = "0.8.47"
|
version = "0.8.48"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"lexical 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"lexical 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"num-rug-adapter 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"num-rug-adapter 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
@@ -580,7 +579,7 @@ dependencies = [
|
|||||||
"nix 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"nix 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"num-rug-adapter 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"num-rug-adapter 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"ordered-float 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"ordered-float 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"prolog_parser 0.8.47 (registry+https://github.com/rust-lang/crates.io-index)",
|
"prolog_parser 0.8.48",
|
||||||
"ref_thread_local 0.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"ref_thread_local 0.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"rug 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"rug 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"rustyline 6.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"rustyline 6.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
@@ -791,7 +790,6 @@ dependencies = [
|
|||||||
"checksum parking_lot 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "92e98c49ab0b7ce5b222f2cc9193fc4efe11c6d0bd4f648e374684a6857b1cfc"
|
"checksum parking_lot 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "92e98c49ab0b7ce5b222f2cc9193fc4efe11c6d0bd4f648e374684a6857b1cfc"
|
||||||
"checksum parking_lot_core 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7582838484df45743c8434fbff785e8edf260c28748353d44bc0da32e0ceabf1"
|
"checksum parking_lot_core 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7582838484df45743c8434fbff785e8edf260c28748353d44bc0da32e0ceabf1"
|
||||||
"checksum proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)" = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759"
|
"checksum proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)" = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759"
|
||||||
"checksum prolog_parser 0.8.47 (registry+https://github.com/rust-lang/crates.io-index)" = "2cf575fc8b91b2d9a9487f13655cffb6f697a5294b74de9b24b6a5fbe987e229"
|
|
||||||
"checksum quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)" = "6ce23b6b870e8f94f81fb0a363d65d86675884b34a09043c81e5562f11c1f8e1"
|
"checksum quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)" = "6ce23b6b870e8f94f81fb0a363d65d86675884b34a09043c81e5562f11c1f8e1"
|
||||||
"checksum rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b"
|
"checksum rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b"
|
||||||
"checksum rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc"
|
"checksum rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc"
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ libc = "0.2.62"
|
|||||||
nix = "0.15.0"
|
nix = "0.15.0"
|
||||||
num-rug-adapter = { optional = true, version = "0.1.1" }
|
num-rug-adapter = { optional = true, version = "0.1.1" }
|
||||||
ordered-float = "0.5.0"
|
ordered-float = "0.5.0"
|
||||||
prolog_parser = { version = "0.8.47", default-features = false }
|
prolog_parser = { version = "0.8.48", path = "../prolog_parser", default-features = false }
|
||||||
ref_thread_local = "0.0.0"
|
ref_thread_local = "0.0.0"
|
||||||
rug = { version = "1.4.0", optional = true }
|
rug = { version = "1.4.0", optional = true }
|
||||||
rustyline = "6.0.0"
|
rustyline = "6.0.0"
|
||||||
|
|||||||
@@ -399,23 +399,27 @@ impl Add<Number> for Number {
|
|||||||
|
|
||||||
fn add(self, rhs: Number) -> Self::Output {
|
fn add(self, rhs: Number) -> Self::Output {
|
||||||
match (self, rhs) {
|
match (self, rhs) {
|
||||||
(Number::Integer(n1), Number::Integer(n2)) => Ok(Number::Integer(n1 + n2)), // add_i
|
(Number::Integer(n1), Number::Integer(n2)) => {
|
||||||
|
Ok(Number::Integer(Rc::new(Integer::from(&*n1) + &*n2))) // add_i
|
||||||
|
}
|
||||||
(Number::Integer(n1), Number::Float(OrderedFloat(n2)))
|
(Number::Integer(n1), Number::Float(OrderedFloat(n2)))
|
||||||
| (Number::Float(OrderedFloat(n2)), Number::Integer(n1)) => {
|
| (Number::Float(OrderedFloat(n2)), Number::Integer(n1)) => {
|
||||||
Ok(Number::Float(add_f(float_i_to_f(&n1)?, n2)?))
|
Ok(Number::Float(add_f(float_i_to_f(&n1)?, n2)?))
|
||||||
}
|
}
|
||||||
(Number::Integer(n1), Number::Rational(n2))
|
(Number::Integer(n1), Number::Rational(n2))
|
||||||
| (Number::Rational(n2), Number::Integer(n1)) => {
|
| (Number::Rational(n2), Number::Integer(n1)) => {
|
||||||
Ok(Number::Rational(Rational::from(n1) + n2))
|
Ok(Number::Rational(Rc::new(Rational::from(&*n1) + &*n2)))
|
||||||
}
|
}
|
||||||
(Number::Rational(n1), Number::Float(OrderedFloat(n2)))
|
(Number::Rational(n1), Number::Float(OrderedFloat(n2)))
|
||||||
| (Number::Float(OrderedFloat(n2)), Number::Rational(n1)) => {
|
| (Number::Float(OrderedFloat(n2)), Number::Rational(n1)) => {
|
||||||
Ok(Number::Float(add_f(float_r_to_f(&n1)?, n2)?))
|
Ok(Number::Float(add_f(float_r_to_f(&n1)?, n2)?))
|
||||||
}
|
}
|
||||||
(Number::Float(OrderedFloat(f1)), Number::Float(OrderedFloat(f2))) => {
|
(Number::Float(OrderedFloat(f1)), Number::Float(OrderedFloat(f2))) => {
|
||||||
Ok(Number::Float(add_f(f1, f2)?))
|
Ok(Number::Float(add_f(f1, f2)?))
|
||||||
}
|
}
|
||||||
(Number::Rational(r1), Number::Rational(r2)) => Ok(Number::Rational(r1 + r2)),
|
(Number::Rational(r1), Number::Rational(r2)) => {
|
||||||
|
Ok(Number::Rational(Rc::new(Rational::from(&*r1) + &*r2)))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -425,9 +429,9 @@ impl Neg for Number {
|
|||||||
|
|
||||||
fn neg(self) -> Self::Output {
|
fn neg(self) -> Self::Output {
|
||||||
match self {
|
match self {
|
||||||
Number::Integer(n) => Number::Integer(-n),
|
Number::Integer(n) => Number::Integer(Rc::new(-Integer::from(&*n))),
|
||||||
Number::Float(OrderedFloat(f)) => Number::Float(OrderedFloat(-f)),
|
Number::Float(OrderedFloat(f)) => Number::Float(OrderedFloat(-f)),
|
||||||
Number::Rational(r) => Number::Rational(-r),
|
Number::Rational(r) => Number::Rational(Rc::new(-Rational::from(&*r))),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -445,14 +449,16 @@ impl Mul<Number> for Number {
|
|||||||
|
|
||||||
fn mul(self, rhs: Number) -> Self::Output {
|
fn mul(self, rhs: Number) -> Self::Output {
|
||||||
match (self, rhs) {
|
match (self, rhs) {
|
||||||
(Number::Integer(n1), Number::Integer(n2)) => Ok(Number::Integer(n1 * n2)), // mul_i
|
(Number::Integer(n1), Number::Integer(n2)) => {
|
||||||
|
Ok(Number::Integer(Rc::new(Integer::from(&*n1) * &*n2))) // mul_i
|
||||||
|
}
|
||||||
(Number::Integer(n1), Number::Float(OrderedFloat(n2)))
|
(Number::Integer(n1), Number::Float(OrderedFloat(n2)))
|
||||||
| (Number::Float(OrderedFloat(n2)), Number::Integer(n1)) => {
|
| (Number::Float(OrderedFloat(n2)), Number::Integer(n1)) => {
|
||||||
Ok(Number::Float(mul_f(float_i_to_f(&n1)?, n2)?))
|
Ok(Number::Float(mul_f(float_i_to_f(&n1)?, n2)?))
|
||||||
}
|
}
|
||||||
(Number::Integer(n1), Number::Rational(n2))
|
(Number::Integer(n1), Number::Rational(n2))
|
||||||
| (Number::Rational(n2), Number::Integer(n1)) => {
|
| (Number::Rational(n2), Number::Integer(n1)) => {
|
||||||
Ok(Number::Rational(Rational::from(n1) * n2))
|
Ok(Number::Rational(Rc::new(Rational::from(&*n1) * &*n2)))
|
||||||
}
|
}
|
||||||
(Number::Rational(n1), Number::Float(OrderedFloat(n2)))
|
(Number::Rational(n1), Number::Float(OrderedFloat(n2)))
|
||||||
| (Number::Float(OrderedFloat(n2)), Number::Rational(n1)) => {
|
| (Number::Float(OrderedFloat(n2)), Number::Rational(n1)) => {
|
||||||
@@ -461,7 +467,9 @@ impl Mul<Number> for Number {
|
|||||||
(Number::Float(OrderedFloat(f1)), Number::Float(OrderedFloat(f2))) => {
|
(Number::Float(OrderedFloat(f1)), Number::Float(OrderedFloat(f2))) => {
|
||||||
Ok(Number::Float(mul_f(f1, f2)?))
|
Ok(Number::Float(mul_f(f1, f2)?))
|
||||||
}
|
}
|
||||||
(Number::Rational(r1), Number::Rational(r2)) => Ok(Number::Rational(r1 * r2)),
|
(Number::Rational(r1), Number::Rational(r2)) => {
|
||||||
|
Ok(Number::Rational(Rc::new(Rational::from(&*r1) * &*r2)))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -539,8 +547,8 @@ impl Ord for Number {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Computes n ^ power. Ignores the sign of power.
|
// Computes n ^ power. Ignores the sign of power.
|
||||||
pub fn binary_pow(mut n: Integer, power: Integer) -> Integer {
|
pub fn binary_pow(mut n: Integer, power: &Integer) -> Integer {
|
||||||
let mut power = power.abs();
|
let mut power = Integer::from(power.abs_ref());
|
||||||
|
|
||||||
if power == 0 {
|
if power == 0 {
|
||||||
return Integer::from(1);
|
return Integer::from(1);
|
||||||
|
|||||||
@@ -576,8 +576,8 @@ pub struct Module {
|
|||||||
#[derive(Clone, PartialEq, Eq)]
|
#[derive(Clone, PartialEq, Eq)]
|
||||||
pub enum Number {
|
pub enum Number {
|
||||||
Float(OrderedFloat<f64>),
|
Float(OrderedFloat<f64>),
|
||||||
Integer(Integer),
|
Integer(Rc<Integer>),
|
||||||
Rational(Rational),
|
Rational(Rc<Rational>),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for Number {
|
impl Default for Number {
|
||||||
@@ -586,48 +586,51 @@ impl Default for Number {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Number {
|
impl Into<HeapCellValue> for Number {
|
||||||
pub fn to_constant(self) -> Constant {
|
#[inline]
|
||||||
|
fn into(self) -> HeapCellValue {
|
||||||
match self {
|
match self {
|
||||||
Number::Integer(n) => Constant::Integer(n),
|
Number::Integer(n) => HeapCellValue::Integer(n),
|
||||||
Number::Float(f) => Constant::Float(f),
|
Number::Float(f) => HeapCellValue::Addr(Addr::Float(f)),
|
||||||
Number::Rational(r) => Constant::Rational(r),
|
Number::Rational(r) => HeapCellValue::Rational(r),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Number {
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn is_positive(&self) -> bool {
|
pub fn is_positive(&self) -> bool {
|
||||||
match self {
|
match self {
|
||||||
&Number::Integer(ref n) => n > &0,
|
&Number::Integer(ref n) => &**n > &0,
|
||||||
&Number::Float(OrderedFloat(f)) => f.is_sign_positive(),
|
&Number::Float(OrderedFloat(f)) => f.is_sign_positive(),
|
||||||
&Number::Rational(ref r) => r > &0,
|
&Number::Rational(ref r) => &**r > &0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn is_negative(&self) -> bool {
|
pub fn is_negative(&self) -> bool {
|
||||||
match self {
|
match self {
|
||||||
&Number::Integer(ref n) => n < &0,
|
&Number::Integer(ref n) => &**n < &0,
|
||||||
&Number::Float(OrderedFloat(f)) => f.is_sign_negative(),
|
&Number::Float(OrderedFloat(f)) => f.is_sign_negative(),
|
||||||
&Number::Rational(ref r) => r < &0,
|
&Number::Rational(ref r) => &**r < &0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn is_zero(&self) -> bool {
|
pub fn is_zero(&self) -> bool {
|
||||||
match self {
|
match self {
|
||||||
&Number::Integer(ref n) => n == &0,
|
&Number::Integer(ref n) => &**n == &0,
|
||||||
&Number::Float(f) => f == OrderedFloat(0f64),
|
&Number::Float(f) => f == OrderedFloat(0f64),
|
||||||
&Number::Rational(ref r) => r == &0,
|
&Number::Rational(ref r) => &**r == &0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn abs(self) -> Self {
|
pub fn abs(self) -> Self {
|
||||||
match self {
|
match self {
|
||||||
Number::Integer(n) => Number::Integer(n.abs()),
|
Number::Integer(n) => Number::Integer(Rc::new(Integer::from(n.abs_ref()))),
|
||||||
Number::Float(f) => Number::Float(OrderedFloat(f.abs())),
|
Number::Float(f) => Number::Float(OrderedFloat(f.abs())),
|
||||||
Number::Rational(r) => Number::Rational(r.abs()),
|
Number::Rational(r) => Number::Rational(Rc::new(Rational::from(r.abs_ref()))),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,3 @@
|
|||||||
use prolog_parser::ast::*;
|
|
||||||
|
|
||||||
use crate::prolog::machine::machine_indices::*;
|
use crate::prolog::machine::machine_indices::*;
|
||||||
use crate::prolog::machine::machine_state::*;
|
use crate::prolog::machine::machine_state::*;
|
||||||
|
|
||||||
@@ -22,25 +20,33 @@ impl<'a> HCPreOrderIterator<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
pub fn machine_st(&self) -> &MachineState {
|
pub fn machine_st(&self) -> &MachineState {
|
||||||
&self.machine_st
|
&self.machine_st
|
||||||
}
|
}
|
||||||
|
|
||||||
fn follow_heap(&mut self, h: usize) -> Addr {
|
fn follow_heap(&mut self, h: usize) -> Addr {
|
||||||
match &self.machine_st.heap[h] {
|
match &self.machine_st.heap[h] {
|
||||||
HeapCellValue::NamedStr(arity, _, _) => {
|
&HeapCellValue::NamedStr(arity, _, _) => {
|
||||||
for idx in (1..arity + 1).rev() {
|
for idx in (1 .. arity + 1).rev() {
|
||||||
self.state_stack.push(Addr::HeapCell(h + idx));
|
self.state_stack.push(Addr::HeapCell(h + idx));
|
||||||
}
|
}
|
||||||
|
|
||||||
Addr::Str(h)
|
Addr::Str(h)
|
||||||
}
|
}
|
||||||
HeapCellValue::Addr(ref a) => {
|
&HeapCellValue::Addr(a) => {
|
||||||
self.follow(a.clone())
|
self.follow(a)
|
||||||
}
|
}
|
||||||
HeapCellValue::PartialString(_) => {
|
HeapCellValue::PartialString(_) => {
|
||||||
self.follow(Addr::PStrLocation(h, 0))
|
self.follow(Addr::PStrLocation(h, 0))
|
||||||
}
|
}
|
||||||
|
HeapCellValue::Atom(..) | HeapCellValue::DBRef(_)
|
||||||
|
| HeapCellValue::Integer(_) | HeapCellValue::Rational(_) => {
|
||||||
|
Addr::Con(h)
|
||||||
|
}
|
||||||
|
HeapCellValue::Stream(_) => {
|
||||||
|
Addr::Stream(h)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -51,30 +57,6 @@ impl<'a> HCPreOrderIterator<'a> {
|
|||||||
let da = self.machine_st.store(self.machine_st.deref(addr));
|
let da = self.machine_st.store(self.machine_st.deref(addr));
|
||||||
|
|
||||||
match da {
|
match da {
|
||||||
Addr::Con(Constant::String(n, s)) => {
|
|
||||||
if !self.machine_st.machine_flags().double_quotes.is_atom() {
|
|
||||||
if s.len() > n {
|
|
||||||
if let Some(c) = s[n ..].chars().next() {
|
|
||||||
let o = c.len_utf8();
|
|
||||||
|
|
||||||
self.state_stack.push(Addr::Con(Constant::String(n+o, s.clone())));
|
|
||||||
|
|
||||||
if self.machine_st.machine_flags().double_quotes.is_codes() {
|
|
||||||
self.state_stack.push(Addr::Con(Constant::CharCode(c as u32)));
|
|
||||||
} else {
|
|
||||||
self.state_stack.push(Addr::Con(Constant::Char(c)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return Addr::Con(Constant::EmptyList);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Addr::Con(Constant::String(n, s))
|
|
||||||
}
|
|
||||||
Addr::Con(_) | Addr::DBRef(_) | Addr::Stream(_) => {
|
|
||||||
da
|
|
||||||
}
|
|
||||||
Addr::Lis(a) => {
|
Addr::Lis(a) => {
|
||||||
self.state_stack.push(Addr::HeapCell(a + 1));
|
self.state_stack.push(Addr::HeapCell(a + 1));
|
||||||
self.state_stack.push(Addr::HeapCell(a));
|
self.state_stack.push(Addr::HeapCell(a));
|
||||||
@@ -83,16 +65,14 @@ impl<'a> HCPreOrderIterator<'a> {
|
|||||||
}
|
}
|
||||||
Addr::PStrLocation(h, n) => {
|
Addr::PStrLocation(h, n) => {
|
||||||
if let HeapCellValue::PartialString(ref pstr) = &self.machine_st.heap[h] {
|
if let HeapCellValue::PartialString(ref pstr) = &self.machine_st.heap[h] {
|
||||||
let s = pstr.block_as_str();
|
if let Some(c) = pstr.range_from(n ..).next() {
|
||||||
|
if !pstr.at_end(n + c.len_utf8()) {
|
||||||
if let Some(c) = s[n ..].chars().next() {
|
|
||||||
if pstr.len() > n + c.len_utf8() {
|
|
||||||
self.state_stack.push(Addr::PStrLocation(h, n + c.len_utf8()));
|
self.state_stack.push(Addr::PStrLocation(h, n + c.len_utf8()));
|
||||||
} else {
|
} else {
|
||||||
self.state_stack.push(Addr::HeapCell(h + 1));
|
self.state_stack.push(Addr::HeapCell(h + 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
self.state_stack.push(Addr::Con(Constant::Char(c)));
|
self.state_stack.push(Addr::Char(c));
|
||||||
} else {
|
} else {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
}
|
}
|
||||||
@@ -102,66 +82,52 @@ impl<'a> HCPreOrderIterator<'a> {
|
|||||||
|
|
||||||
Addr::PStrLocation(h, n)
|
Addr::PStrLocation(h, n)
|
||||||
}
|
}
|
||||||
Addr::AttrVar(_) | Addr::HeapCell(_) | Addr::StackCell(_, _) => {
|
|
||||||
da
|
|
||||||
}
|
|
||||||
Addr::Str(s) => {
|
Addr::Str(s) => {
|
||||||
self.follow_heap(s) // record terms of structure.
|
self.follow_heap(s) // record terms of structure.
|
||||||
}
|
}
|
||||||
|
Addr::Con(h) => {
|
||||||
|
if let HeapCellValue::PartialString(_) = &self.machine_st.heap[h] {
|
||||||
|
self.state_stack.push(Addr::HeapCell(h + 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
Addr::Con(h)
|
||||||
|
}
|
||||||
|
da => {
|
||||||
|
da
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Iterator for HCPreOrderIterator<'a> {
|
impl<'a> Iterator for HCPreOrderIterator<'a> {
|
||||||
type Item = HeapCellValue;
|
type Item = Addr;
|
||||||
|
|
||||||
fn next(&mut self) -> Option<Self::Item> {
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
self.state_stack.pop().map(|a| match self.follow(a) {
|
self.state_stack.pop().map(|a| self.follow(a))
|
||||||
Addr::HeapCell(h) => {
|
|
||||||
HeapCellValue::Addr(self.machine_st.heap[h].as_addr(h))
|
|
||||||
}
|
|
||||||
Addr::Str(s) => {
|
|
||||||
match &self.machine_st.heap[s] {
|
|
||||||
val @ HeapCellValue::NamedStr(..) => {
|
|
||||||
val.clone()
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
unreachable!()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Addr::StackCell(fr, sc) => {
|
|
||||||
HeapCellValue::Addr(self.machine_st.stack.index_and_frame(fr)[sc].clone())
|
|
||||||
}
|
|
||||||
da => {
|
|
||||||
HeapCellValue::Addr(da)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait MutStackHCIterator
|
pub trait MutStackHCIterator
|
||||||
where
|
where Self: Iterator<Item = Addr>
|
||||||
Self: Iterator<Item = HeapCellValue>,
|
|
||||||
{
|
{
|
||||||
fn stack(&mut self) -> &mut Vec<Addr>;
|
fn stack(&mut self) -> &mut Vec<Addr>;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct HCPostOrderIterator<HCIter> {
|
pub struct HCPostOrderIterator<'a> {
|
||||||
base_iter: HCIter,
|
base_iter: HCPreOrderIterator<'a>,
|
||||||
parent_stack: Vec<(usize, HeapCellValue)>, // number of children, parent node.
|
parent_stack: Vec<(usize, Addr)>, // number of children, parent node.
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<HCIter> Deref for HCPostOrderIterator<HCIter> {
|
impl<'a> Deref for HCPostOrderIterator<'a> {
|
||||||
type Target = HCIter;
|
type Target = HCPreOrderIterator<'a>;
|
||||||
|
|
||||||
fn deref(&self) -> &Self::Target {
|
fn deref(&self) -> &Self::Target {
|
||||||
&self.base_iter
|
&self.base_iter
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<HCIter: Iterator<Item = HeapCellValue>> HCPostOrderIterator<HCIter> {
|
impl<'a> HCPostOrderIterator<'a> {
|
||||||
pub fn new(base_iter: HCIter) -> Self {
|
pub fn new(base_iter: HCPreOrderIterator<'a>) -> Self {
|
||||||
HCPostOrderIterator {
|
HCPostOrderIterator {
|
||||||
base_iter,
|
base_iter,
|
||||||
parent_stack: vec![],
|
parent_stack: vec![],
|
||||||
@@ -169,8 +135,8 @@ impl<HCIter: Iterator<Item = HeapCellValue>> HCPostOrderIterator<HCIter> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<HCIter: Iterator<Item = HeapCellValue>> Iterator for HCPostOrderIterator<HCIter> {
|
impl<'a> Iterator for HCPostOrderIterator<'a> {
|
||||||
type Item = HeapCellValue;
|
type Item = Addr;
|
||||||
|
|
||||||
fn next(&mut self) -> Option<Self::Item> {
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
loop {
|
loop {
|
||||||
@@ -183,15 +149,23 @@ impl<HCIter: Iterator<Item = HeapCellValue>> Iterator for HCPostOrderIterator<HC
|
|||||||
}
|
}
|
||||||
|
|
||||||
if let Some(item) = self.base_iter.next() {
|
if let Some(item) = self.base_iter.next() {
|
||||||
match item {
|
match self.base_iter.machine_st.heap.index_addr(&item).as_ref() {
|
||||||
HeapCellValue::NamedStr(arity, name, fix) => self
|
&HeapCellValue::NamedStr(arity, ..) => {
|
||||||
.parent_stack
|
self.parent_stack.push((arity, item));
|
||||||
.push((arity, HeapCellValue::NamedStr(arity, name, fix))),
|
}
|
||||||
HeapCellValue::Addr(Addr::Lis(a)) => self
|
&HeapCellValue::Addr(Addr::Lis(a)) => {
|
||||||
.parent_stack
|
self.parent_stack.push((2, Addr::Lis(a)));
|
||||||
.push((2, HeapCellValue::Addr(Addr::Lis(a)))),
|
}
|
||||||
child_node => {
|
&HeapCellValue::Addr(Addr::PStrLocation(h, n)) => {
|
||||||
return Some(child_node);
|
if let HeapCellValue::PartialString(ref pstr) = &self.machine_st.heap[h] {
|
||||||
|
let c = pstr.range_from(n ..).next().unwrap();
|
||||||
|
self.parent_stack.push((2, Addr::PStrLocation(h, n + c.len_utf8())));
|
||||||
|
} else {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
return Some(item);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -201,21 +175,16 @@ impl<HCIter: Iterator<Item = HeapCellValue>> Iterator for HCPostOrderIterator<HC
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type HCProperPostOrderIterator<'a> = HCPostOrderIterator<HCPreOrderIterator<'a>>;
|
|
||||||
|
|
||||||
impl MachineState {
|
impl MachineState {
|
||||||
pub fn pre_order_iter<'a>(&'a self, a: Addr) -> HCPreOrderIterator<'a> {
|
pub fn pre_order_iter<'a>(&'a self, a: Addr) -> HCPreOrderIterator<'a> {
|
||||||
HCPreOrderIterator::new(self, a)
|
HCPreOrderIterator::new(self, a)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn post_order_iter<'a>(&'a self, a: Addr) -> HCProperPostOrderIterator<'a> {
|
pub fn post_order_iter<'a>(&'a self, a: Addr) -> HCPostOrderIterator<'a> {
|
||||||
HCPostOrderIterator::new(HCPreOrderIterator::new(self, a))
|
HCPostOrderIterator::new(HCPreOrderIterator::new(self, a))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn acyclic_pre_order_iter<'a>(
|
pub fn acyclic_pre_order_iter<'a>(&'a self, a: Addr,) -> HCAcyclicIterator<'a> {
|
||||||
&'a self,
|
|
||||||
a: Addr,
|
|
||||||
) -> HCAcyclicIterator<HCPreOrderIterator<'a>> {
|
|
||||||
HCAcyclicIterator::new(HCPreOrderIterator::new(self, a))
|
HCAcyclicIterator::new(HCPreOrderIterator::new(self, a))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -223,7 +192,7 @@ impl MachineState {
|
|||||||
&'a self,
|
&'a self,
|
||||||
a1: Addr,
|
a1: Addr,
|
||||||
a2: Addr,
|
a2: Addr,
|
||||||
) -> HCZippedAcyclicIterator<HCPreOrderIterator<'a>> {
|
) -> HCZippedAcyclicIterator<'a> {
|
||||||
HCZippedAcyclicIterator::new(
|
HCZippedAcyclicIterator::new(
|
||||||
HCPreOrderIterator::new(self, a1),
|
HCPreOrderIterator::new(self, a1),
|
||||||
HCPreOrderIterator::new(self, a2),
|
HCPreOrderIterator::new(self, a2),
|
||||||
@@ -237,13 +206,13 @@ impl<'a> MutStackHCIterator for HCPreOrderIterator<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct HCAcyclicIterator<HCIter> {
|
pub struct HCAcyclicIterator<'a> {
|
||||||
iter: HCIter,
|
iter: HCPreOrderIterator<'a>,
|
||||||
seen: IndexSet<Addr>,
|
seen: IndexSet<Addr>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<HCIter: MutStackHCIterator> HCAcyclicIterator<HCIter> {
|
impl<'a> HCAcyclicIterator<'a> {
|
||||||
pub fn new(iter: HCIter) -> Self {
|
pub fn new(iter: HCPreOrderIterator<'a>) -> Self {
|
||||||
HCAcyclicIterator {
|
HCAcyclicIterator {
|
||||||
iter,
|
iter,
|
||||||
seen: IndexSet::new(),
|
seen: IndexSet::new(),
|
||||||
@@ -251,19 +220,17 @@ impl<HCIter: MutStackHCIterator> HCAcyclicIterator<HCIter> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<HCIter> Deref for HCAcyclicIterator<HCIter> {
|
impl<'a> Deref for HCAcyclicIterator<'a> {
|
||||||
type Target = HCIter;
|
type Target = HCPreOrderIterator<'a>;
|
||||||
|
|
||||||
fn deref(&self) -> &Self::Target {
|
fn deref(&self) -> &Self::Target {
|
||||||
&self.iter
|
&self.iter
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<HCIter> Iterator for HCAcyclicIterator<HCIter>
|
impl<'a> Iterator for HCAcyclicIterator<'a>
|
||||||
where
|
|
||||||
HCIter: Iterator<Item = HeapCellValue> + MutStackHCIterator,
|
|
||||||
{
|
{
|
||||||
type Item = HeapCellValue;
|
type Item = Addr;
|
||||||
|
|
||||||
fn next(&mut self) -> Option<Self::Item> {
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
while let Some(addr) = self.iter.stack().pop() {
|
while let Some(addr) = self.iter.stack().pop() {
|
||||||
@@ -279,15 +246,15 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct HCZippedAcyclicIterator<HCIter> {
|
pub struct HCZippedAcyclicIterator<'a> {
|
||||||
i1: HCIter,
|
i1: HCPreOrderIterator<'a>,
|
||||||
i2: HCIter,
|
i2: HCPreOrderIterator<'a>,
|
||||||
seen: IndexSet<(Addr, Addr)>,
|
seen: IndexSet<(Addr, Addr)>,
|
||||||
pub first_to_expire: Ordering,
|
pub first_to_expire: Ordering,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<HCIter: MutStackHCIterator> HCZippedAcyclicIterator<HCIter> {
|
impl<'a> HCZippedAcyclicIterator<'a> {
|
||||||
pub fn new(i1: HCIter, i2: HCIter) -> Self {
|
pub fn new(i1: HCPreOrderIterator<'a>, i2: HCPreOrderIterator<'a>) -> Self {
|
||||||
HCZippedAcyclicIterator {
|
HCZippedAcyclicIterator {
|
||||||
i1,
|
i1,
|
||||||
i2,
|
i2,
|
||||||
@@ -297,11 +264,9 @@ impl<HCIter: MutStackHCIterator> HCZippedAcyclicIterator<HCIter> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<HCIter> Iterator for HCZippedAcyclicIterator<HCIter>
|
impl<'a> Iterator for HCZippedAcyclicIterator<'a>
|
||||||
where
|
|
||||||
HCIter: Iterator<Item = HeapCellValue> + MutStackHCIterator,
|
|
||||||
{
|
{
|
||||||
type Item = (HeapCellValue, HeapCellValue);
|
type Item = (Addr, Addr);
|
||||||
|
|
||||||
fn next(&mut self) -> Option<Self::Item> {
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
while let (Some(a1), Some(a2)) = (self.i1.stack().pop(), self.i2.stack().pop()) {
|
while let (Some(a1), Some(a2)) = (self.i1.stack().pop(), self.i2.stack().pop()) {
|
||||||
@@ -324,7 +289,9 @@ where
|
|||||||
self.first_to_expire = Ordering::Less;
|
self.first_to_expire = Ordering::Less;
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
_ => None,
|
_ => {
|
||||||
|
None
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ use prolog_parser::ast::*;
|
|||||||
use crate::prolog::clause_types::*;
|
use crate::prolog::clause_types::*;
|
||||||
use crate::prolog::forms::*;
|
use crate::prolog::forms::*;
|
||||||
use crate::prolog::heap_iter::*;
|
use crate::prolog::heap_iter::*;
|
||||||
|
use crate::prolog::machine::heap::*;
|
||||||
use crate::prolog::machine::machine_indices::*;
|
use crate::prolog::machine::machine_indices::*;
|
||||||
use crate::prolog::machine::machine_state::*;
|
use crate::prolog::machine::machine_state::*;
|
||||||
use crate::prolog::ordered_float::OrderedFloat;
|
use crate::prolog::ordered_float::OrderedFloat;
|
||||||
@@ -88,14 +89,17 @@ impl<'a> HCPreOrderIterator<'a> {
|
|||||||
*/
|
*/
|
||||||
fn leftmost_leaf_has_property<P>(&self, property_check: P) -> bool
|
fn leftmost_leaf_has_property<P>(&self, property_check: P) -> bool
|
||||||
where
|
where
|
||||||
P: Fn(Constant) -> bool,
|
P: Fn(Addr, &Heap) -> bool,
|
||||||
{
|
{
|
||||||
let mut addr = match self.state_stack.last().cloned() {
|
let mut addr = match self.state_stack.last().cloned() {
|
||||||
Some(addr) => addr,
|
Some(addr) => addr,
|
||||||
None => return false,
|
None => return false,
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut parent_spec = DirectedOp::Left(clause_name!("-"), SharedOpDesc::new(200, FY));
|
let mut parent_spec = DirectedOp::Left(
|
||||||
|
clause_name!("-"),
|
||||||
|
SharedOpDesc::new(200, FY),
|
||||||
|
);
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
match self.machine_st.store(self.machine_st.deref(addr)) {
|
match self.machine_st.store(self.machine_st.deref(addr)) {
|
||||||
@@ -110,29 +114,28 @@ impl<'a> HCPreOrderIterator<'a> {
|
|||||||
parent_spec = DirectedOp::Right(name.clone(), spec.clone());
|
parent_spec = DirectedOp::Right(name.clone(), spec.clone());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => return false,
|
_ => {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
},
|
},
|
||||||
Addr::Con(Constant::Integer(n)) => return property_check(Constant::Integer(n)),
|
addr => {
|
||||||
Addr::Con(Constant::Float(n)) => return property_check(Constant::Float(n)),
|
return property_check(addr, &self.machine_st.heap);
|
||||||
Addr::Con(Constant::Rational(n)) => return property_check(Constant::Rational(n)),
|
}
|
||||||
_ => return false,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn immediate_leaf_has_property<P>(&self, property_check: P) -> bool
|
fn immediate_leaf_has_property<P>(&self, property_check: P) -> bool
|
||||||
where
|
where
|
||||||
P: Fn(Constant) -> bool,
|
P: Fn(Addr, &Heap) -> bool,
|
||||||
{
|
{
|
||||||
let addr = match self.state_stack.last().cloned() {
|
let addr = match self.state_stack.last().cloned() {
|
||||||
Some(addr) => addr,
|
Some(addr) => addr,
|
||||||
None => return false,
|
None => return false,
|
||||||
};
|
};
|
||||||
|
|
||||||
match self.machine_st.store(self.machine_st.deref(addr)) {
|
let addr = self.machine_st.store(self.machine_st.deref(addr));
|
||||||
Addr::Con(c) => property_check(c),
|
property_check(addr, &self.machine_st.heap)
|
||||||
_ => false,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -261,13 +264,29 @@ fn is_numbered_var(ct: &ClauseType, arity: usize) -> bool {
|
|||||||
#[inline]
|
#[inline]
|
||||||
fn negated_op_needs_bracketing(iter: &HCPreOrderIterator, op: &Option<DirectedOp>) -> bool {
|
fn negated_op_needs_bracketing(iter: &HCPreOrderIterator, op: &Option<DirectedOp>) -> bool {
|
||||||
if let &Some(ref op) = op {
|
if let &Some(ref op) = op {
|
||||||
op.is_negative_sign()
|
op.is_negative_sign() && iter.leftmost_leaf_has_property(|addr, heap| {
|
||||||
&& iter.leftmost_leaf_has_property(|c| match c {
|
match addr {
|
||||||
Constant::Integer(n) => n > 0,
|
Addr::Con(h) => {
|
||||||
Constant::Float(f) => f > OrderedFloat(0f64),
|
match &heap[h] {
|
||||||
Constant::Rational(r) => r > 0,
|
HeapCellValue::Integer(ref n) => {
|
||||||
_ => false,
|
&**n > &0
|
||||||
})
|
}
|
||||||
|
&HeapCellValue::Rational(ref r) => {
|
||||||
|
&**r > &0
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Addr::Float(f) => {
|
||||||
|
f > OrderedFloat(0f64)
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
} else {
|
} else {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
@@ -293,8 +312,16 @@ fn numbervar(n: Integer) -> Var {
|
|||||||
impl MachineState {
|
impl MachineState {
|
||||||
pub fn numbervar(&self, offset: &Integer, addr: Addr) -> Option<Var> {
|
pub fn numbervar(&self, offset: &Integer, addr: Addr) -> Option<Var> {
|
||||||
match self.store(self.deref(addr)) {
|
match self.store(self.deref(addr)) {
|
||||||
Addr::Con(Constant::Integer(ref n)) if n >= &0 => {
|
Addr::Con(h) => {
|
||||||
Some(numbervar(Integer::from(offset + n)))
|
if let &HeapCellValue::Integer(ref n) = &self.heap[h] {
|
||||||
|
if &**n >= &0 {
|
||||||
|
Some(numbervar(Integer::from(offset + &**n)))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
None
|
None
|
||||||
@@ -823,7 +850,7 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
|
|||||||
fn check_for_seen(
|
fn check_for_seen(
|
||||||
&mut self,
|
&mut self,
|
||||||
iter: &mut HCPreOrderIterator,
|
iter: &mut HCPreOrderIterator,
|
||||||
) -> Option<HeapCellValue> {
|
) -> Option<Addr> {
|
||||||
iter.stack().last().cloned().and_then(|addr| {
|
iter.stack().last().cloned().and_then(|addr| {
|
||||||
let addr = self.machine_st.store(self.machine_st.deref(addr));
|
let addr = self.machine_st.store(self.machine_st.deref(addr));
|
||||||
|
|
||||||
@@ -848,7 +875,9 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
|
|||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
let offset = match functor_location(&addr) {
|
let offset = match functor_location(&addr) {
|
||||||
Some(offset) => offset,
|
Some(offset) => {
|
||||||
|
offset
|
||||||
|
}
|
||||||
None => {
|
None => {
|
||||||
return iter.next();
|
return iter.next();
|
||||||
}
|
}
|
||||||
@@ -969,7 +998,7 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn print_char(&mut self, is_quoted: bool, c: char)
|
fn print_char(&mut self, is_quoted: bool, c: char)
|
||||||
{
|
{
|
||||||
if non_quoted_token(once(c)) {
|
if non_quoted_token(once(c)) {
|
||||||
let c = char_to_string(false, c);
|
let c = char_to_string(false, c);
|
||||||
|
|
||||||
@@ -993,178 +1022,130 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn print_constant(
|
|
||||||
&mut self,
|
|
||||||
iter: &mut HCPreOrderIterator,
|
|
||||||
max_depth: usize,
|
|
||||||
c: Constant,
|
|
||||||
op: &Option<DirectedOp>,
|
|
||||||
) {
|
|
||||||
match c {
|
|
||||||
Constant::Atom(atom, spec) => {
|
|
||||||
if let Some(_) = fetch_atom_op_spec(atom.clone(), spec, self.op_dir) {
|
|
||||||
let mut result = String::new();
|
|
||||||
|
|
||||||
if let Some(ref op) = op {
|
|
||||||
if self.outputter.ends_with(&format!(" {}", op.as_str())) {
|
|
||||||
result.push(' ');
|
|
||||||
}
|
|
||||||
|
|
||||||
result.push('(');
|
|
||||||
}
|
|
||||||
|
|
||||||
result += &self.print_op_addendum(atom.as_str());
|
|
||||||
|
|
||||||
if op.is_some() {
|
|
||||||
result.push(')');
|
|
||||||
}
|
|
||||||
|
|
||||||
push_space_if_amb!(self, &result, {
|
|
||||||
self.append_str(&result);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
push_space_if_amb!(self, atom.as_str(), {
|
|
||||||
self.print_atom(&atom);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Constant::CharCode(c) => {
|
|
||||||
self.append_str(&format!("{}", c as u32));
|
|
||||||
}
|
|
||||||
Constant::Char(c) => {
|
|
||||||
self.print_char(self.quoted, c);
|
|
||||||
}
|
|
||||||
Constant::CutPoint(b) => {
|
|
||||||
self.append_str(&format!("{}", b));
|
|
||||||
}
|
|
||||||
Constant::EmptyList => {
|
|
||||||
self.append_str("[]");
|
|
||||||
}
|
|
||||||
Constant::Integer(n) => {
|
|
||||||
self.print_number(Number::Integer(n), op);
|
|
||||||
}
|
|
||||||
Constant::Float(n) => {
|
|
||||||
self.print_number(Number::Float(n), op);
|
|
||||||
}
|
|
||||||
Constant::Rational(n) => {
|
|
||||||
self.print_number(Number::Rational(n), op);
|
|
||||||
}
|
|
||||||
Constant::String(n, s) if self.print_strings_as_strs => {
|
|
||||||
self.print_string_as_str(iter, n, s);
|
|
||||||
}
|
|
||||||
Constant::String(n, s) => {
|
|
||||||
self.print_string(iter, max_depth, n, s);
|
|
||||||
}
|
|
||||||
Constant::Usize(i) => {
|
|
||||||
self.append_str(&format!("u{}", i));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn print_string_as_str(
|
fn print_string_as_str(
|
||||||
&mut self,
|
&mut self,
|
||||||
iter: &mut HCPreOrderIterator,
|
mut h: usize,
|
||||||
offset: usize,
|
mut offset: usize,
|
||||||
s: Rc<String>,
|
quoted: bool,
|
||||||
) {
|
) {
|
||||||
let atom = String::from_iter(s[offset ..].chars().map(|c| {
|
|
||||||
char_to_string(true, c)
|
|
||||||
}));
|
|
||||||
|
|
||||||
self.push_char('"');
|
|
||||||
self.append_str(&atom);
|
|
||||||
self.push_char('"');
|
self.push_char('"');
|
||||||
|
|
||||||
// eliminate lingering elements on the iterator stack (the
|
while let HeapCellValue::PartialString(ref pstr) = &self.machine_st.heap[h] {
|
||||||
// head and tail) which are there to treat the string as a
|
let atom = String::from_iter(pstr.range_from(offset ..).map(|c| {
|
||||||
// list.
|
char_to_string(quoted, c)
|
||||||
iter.stack().pop();
|
}));
|
||||||
iter.stack().pop();
|
|
||||||
|
self.append_str(&atom);
|
||||||
|
|
||||||
|
h += 2;
|
||||||
|
offset = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.push_char('"');
|
||||||
}
|
}
|
||||||
|
|
||||||
fn print_string(
|
fn print_string(
|
||||||
&mut self,
|
&mut self,
|
||||||
iter: &mut HCPreOrderIterator,
|
|
||||||
mut max_depth: usize,
|
mut max_depth: usize,
|
||||||
offset: usize,
|
mut h: usize,
|
||||||
s: Rc<String>)
|
mut offset: usize,
|
||||||
|
)
|
||||||
{
|
{
|
||||||
if !self.machine_st.machine_flags().double_quotes.is_atom() {
|
if !self.machine_st.machine_flags().double_quotes.is_atom() {
|
||||||
if self.check_max_depth(&mut max_depth) {
|
if self.check_max_depth(&mut max_depth) {
|
||||||
self.state_stack.push(TokenOrRedirect::Atom(clause_name!("...")));
|
self.state_stack.push(TokenOrRedirect::Atom(clause_name!("...")));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if s.len() <= offset && !self.at_cdr("") {
|
while let HeapCellValue::PartialString(ref pstr) = &self.machine_st.heap[h] {
|
||||||
self.append_str("[]");
|
if pstr.at_end(offset) && !self.at_cdr("") {
|
||||||
} else if self.ignore_ops {
|
if let HeapCellValue::Addr(Addr::EmptyList) = &self.machine_st.heap[h+1] {
|
||||||
let mut char_count = 0;
|
self.append_str("[]");
|
||||||
let mut byte_len = 0;
|
break;
|
||||||
|
|
||||||
let iter: Box<dyn Iterator<Item=char>> =
|
|
||||||
if self.max_depth == 0 {
|
|
||||||
Box::new(s[offset ..].chars())
|
|
||||||
} else {
|
} else {
|
||||||
Box::new(s[offset ..].chars().take(max_depth))
|
h += 2;
|
||||||
};
|
offset = 0;
|
||||||
|
}
|
||||||
|
} else if self.ignore_ops {
|
||||||
|
let iter: Box<dyn Iterator<Item=char>> =
|
||||||
|
if self.max_depth == 0 {
|
||||||
|
Box::new(pstr.range_from(offset ..))
|
||||||
|
} else {
|
||||||
|
Box::new(pstr.range_from(offset ..).take(max_depth))
|
||||||
|
};
|
||||||
|
|
||||||
for c in iter {
|
let mut char_count = 0;
|
||||||
self.print_char(self.quoted, '.');
|
let mut byte_len = 0;
|
||||||
self.push_char('(');
|
|
||||||
|
|
||||||
self.print_char(self.quoted, c);
|
for c in iter {
|
||||||
self.push_char(',');
|
self.print_char(self.quoted, '.');
|
||||||
|
self.push_char('(');
|
||||||
|
|
||||||
char_count += 1;
|
self.print_char(self.quoted, c);
|
||||||
byte_len += c.len_utf8();
|
self.push_char(',');
|
||||||
|
|
||||||
|
char_count += 1;
|
||||||
|
byte_len += c.len_utf8();
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut at_end = false;
|
||||||
|
|
||||||
|
if self.max_depth > 0 && !pstr.at_end(offset + byte_len) {
|
||||||
|
self.append_str("...");
|
||||||
|
at_end = true;
|
||||||
|
} else {
|
||||||
|
if let HeapCellValue::Addr(Addr::EmptyList) = &self.machine_st.heap[h+1] {
|
||||||
|
self.append_str("[]");
|
||||||
|
at_end = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for _ in 0 .. char_count {
|
||||||
|
self.push_char(')');
|
||||||
|
}
|
||||||
|
|
||||||
|
if at_end {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
max_depth -= char_count;
|
||||||
|
} else {
|
||||||
|
self.push_char('[');
|
||||||
|
|
||||||
|
let iter: Box<dyn Iterator<Item=char>> =
|
||||||
|
if self.max_depth == 0 {
|
||||||
|
Box::new(pstr.range_from(offset ..))
|
||||||
|
} else {
|
||||||
|
Box::new(pstr.range_from(offset ..).take(max_depth))
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut byte_len = 0;
|
||||||
|
let mut char_count = 0;
|
||||||
|
|
||||||
|
for c in iter {
|
||||||
|
self.print_char(false, c);
|
||||||
|
self.push_char(',');
|
||||||
|
|
||||||
|
byte_len += c.len_utf8();
|
||||||
|
char_count += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if self.max_depth > 0 && !pstr.at_end(offset + byte_len) {
|
||||||
|
self.append_str("...|...]");
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
self.outputter.truncate(self.outputter.len() - ','.len_utf8());
|
||||||
|
self.push_char(']');
|
||||||
|
}
|
||||||
|
|
||||||
|
max_depth -= char_count;
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.max_depth > 0 && byte_len < s[offset ..].len() {
|
h += 2;
|
||||||
self.append_str("...");
|
offset = 0;
|
||||||
} else {
|
|
||||||
self.append_str("[]");
|
|
||||||
}
|
|
||||||
|
|
||||||
for _ in 0 .. char_count {
|
|
||||||
self.push_char(')');
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
self.push_char('[');
|
|
||||||
|
|
||||||
let iter: Box<dyn Iterator<Item=char>> =
|
|
||||||
if self.max_depth == 0 {
|
|
||||||
Box::new(s[offset ..].chars())
|
|
||||||
} else {
|
|
||||||
Box::new(s[offset ..].chars().take(max_depth))
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut byte_len = 0;
|
|
||||||
|
|
||||||
for c in iter {
|
|
||||||
self.print_char(false, c);
|
|
||||||
self.push_char(',');
|
|
||||||
|
|
||||||
byte_len += c.len_utf8();
|
|
||||||
}
|
|
||||||
|
|
||||||
if self.max_depth > 0 && byte_len < s[offset ..].len() {
|
|
||||||
self.append_str("...|...]");
|
|
||||||
} else {
|
|
||||||
self.outputter.truncate(self.outputter.len() - ','.len_utf8());
|
|
||||||
self.push_char(']');
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
iter.stack().pop();
|
|
||||||
iter.stack().pop();
|
|
||||||
} else {
|
} else {
|
||||||
let atom = String::from_iter(s[offset ..].chars().map(|c| {
|
self.print_string_as_str(h, 0, self.quoted);
|
||||||
char_to_string(self.quoted, c)
|
|
||||||
}));
|
|
||||||
|
|
||||||
self.push_char('"');
|
|
||||||
self.append_str(&atom);
|
|
||||||
self.push_char('"');
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1217,21 +1198,22 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
|
|||||||
max_depth: usize,
|
max_depth: usize,
|
||||||
) {
|
) {
|
||||||
let add_brackets = if !self.ignore_ops {
|
let add_brackets = if !self.ignore_ops {
|
||||||
negated_operand
|
negated_operand || if let Some(ref op) = op {
|
||||||
|| if let Some(ref op) = op {
|
if self.numbervars && arity == 1 && name.as_str() == "$VAR" {
|
||||||
if self.numbervars && arity == 1 && name.as_str() == "$VAR" {
|
!iter.immediate_leaf_has_property(|addr, heap| {
|
||||||
!iter.immediate_leaf_has_property(|c| match c {
|
match heap.index_addr(&addr).as_ref() {
|
||||||
Constant::Integer(n) => n >= 0,
|
&HeapCellValue::Integer(ref n) => &**n >= &0,
|
||||||
Constant::Float(f) => f >= OrderedFloat(0f64),
|
&HeapCellValue::Addr(Addr::Float(f)) => f >= OrderedFloat(0f64),
|
||||||
Constant::Rational(r) => r >= 0,
|
&HeapCellValue::Rational(ref r) => &**r >= &0,
|
||||||
_ => false,
|
_ => false
|
||||||
}) && needs_bracketing(&spec, op)
|
}
|
||||||
} else {
|
}) && needs_bracketing(&spec, op)
|
||||||
needs_bracketing(&spec, op)
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
is_functor_redirect && spec.prec() >= 1000
|
needs_bracketing(&spec, op)
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
is_functor_redirect && spec.prec() >= 1000
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
false
|
false
|
||||||
};
|
};
|
||||||
@@ -1264,49 +1246,134 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
|
|||||||
) {
|
) {
|
||||||
let negated_operand = negated_op_needs_bracketing(iter, &op);
|
let negated_operand = negated_op_needs_bracketing(iter, &op);
|
||||||
|
|
||||||
let heap_val = match self.check_for_seen(iter) {
|
let addr = match self.check_for_seen(iter) {
|
||||||
Some(heap_val) => heap_val,
|
Some(addr) => addr,
|
||||||
None => return,
|
None => return,
|
||||||
};
|
};
|
||||||
|
|
||||||
match heap_val {
|
match self.machine_st.heap.index_addr(&addr).as_ref() {
|
||||||
HeapCellValue::NamedStr(arity, name, spec) => {
|
&HeapCellValue::NamedStr(arity, ref name, ref spec) => {
|
||||||
let spec = fetch_op_spec(name.clone(), arity, spec.clone(), self.op_dir);
|
let spec = fetch_op_spec(name.clone(), arity, spec.clone(), self.op_dir);
|
||||||
|
|
||||||
if let Some(spec) = spec {
|
if let Some(spec) = spec {
|
||||||
self.handle_op_as_struct(
|
self.handle_op_as_struct(
|
||||||
name,
|
name.clone(),
|
||||||
arity,
|
arity,
|
||||||
iter,
|
iter,
|
||||||
&op,
|
&op,
|
||||||
is_functor_redirect,
|
is_functor_redirect,
|
||||||
spec,
|
spec.clone(),
|
||||||
negated_operand,
|
negated_operand,
|
||||||
max_depth,
|
max_depth,
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
push_space_if_amb!(self, name.as_str(), {
|
push_space_if_amb!(self, name.as_str(), {
|
||||||
let ct = ClauseType::from(name, arity, spec);
|
let ct = ClauseType::from(name.clone(), arity, spec);
|
||||||
self.format_clause(iter, max_depth, arity, ct);
|
self.format_clause(iter, max_depth, arity, ct);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
HeapCellValue::Addr(Addr::Con(Constant::EmptyList)) => {
|
&HeapCellValue::Atom(ref atom, ref spec) => {
|
||||||
|
if let Some(_) = fetch_atom_op_spec(atom.clone(), spec.clone(), self.op_dir) {
|
||||||
|
let mut result = String::new();
|
||||||
|
|
||||||
|
if let Some(ref op) = op {
|
||||||
|
if self.outputter.ends_with(&format!(" {}", op.as_str())) {
|
||||||
|
result.push(' ');
|
||||||
|
}
|
||||||
|
|
||||||
|
result.push('(');
|
||||||
|
}
|
||||||
|
|
||||||
|
result += &self.print_op_addendum(atom.as_str());
|
||||||
|
|
||||||
|
if op.is_some() {
|
||||||
|
result.push(')');
|
||||||
|
}
|
||||||
|
|
||||||
|
push_space_if_amb!(self, &result, {
|
||||||
|
self.append_str(&result);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
push_space_if_amb!(self, atom.as_str(), {
|
||||||
|
self.print_atom(&atom);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&HeapCellValue::Addr(Addr::CharCode(c)) => {
|
||||||
|
self.append_str(&format!("{}", c as u32));
|
||||||
|
}
|
||||||
|
&HeapCellValue::Addr(Addr::Char(c)) => {
|
||||||
|
self.print_char(self.quoted, c);
|
||||||
|
}
|
||||||
|
&HeapCellValue::Addr(Addr::CutPoint(b)) => {
|
||||||
|
self.append_str(&format!("{}", b));
|
||||||
|
}
|
||||||
|
&HeapCellValue::Addr(Addr::EmptyList) => {
|
||||||
if !self.at_cdr("") {
|
if !self.at_cdr("") {
|
||||||
self.append_str("[]");
|
self.append_str("[]");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
HeapCellValue::Addr(Addr::Con(c)) => {
|
&HeapCellValue::Addr(Addr::Float(n)) => {
|
||||||
self.print_constant(iter, max_depth, c, &op);
|
self.print_number(Number::Float(n), &op);
|
||||||
}
|
}
|
||||||
HeapCellValue::Addr(Addr::Lis(_)) | HeapCellValue::Addr(Addr::PStrLocation(..)) => {
|
&HeapCellValue::Addr(Addr::Usize(u)) => {
|
||||||
|
self.append_str(&format!("{}", u));
|
||||||
|
}
|
||||||
|
&HeapCellValue::Addr(Addr::PStrLocation(..))
|
||||||
|
if !self.machine_st.flags.double_quotes.is_atom() => {
|
||||||
|
if self.ignore_ops {
|
||||||
|
self.format_struct(iter, max_depth, 2, clause_name!("."));
|
||||||
|
} else {
|
||||||
|
self.push_list(iter, max_depth);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&HeapCellValue::Addr(Addr::PStrLocation(h, n)) => {
|
||||||
|
if let HeapCellValue::PartialString(_) = &self.machine_st.heap[h] {
|
||||||
|
self.print_string(max_depth, h, n);
|
||||||
|
|
||||||
|
iter.stack().pop();
|
||||||
|
iter.stack().pop();
|
||||||
|
} else {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&HeapCellValue::Addr(Addr::Lis(_)) => {
|
||||||
if self.ignore_ops {
|
if self.ignore_ops {
|
||||||
self.format_struct(iter, max_depth, 2, clause_name!("."));
|
self.format_struct(iter, max_depth, 2, clause_name!("."));
|
||||||
} else {
|
} else {
|
||||||
self.push_list(iter, max_depth);
|
self.push_list(iter, max_depth);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
HeapCellValue::Addr(Addr::Stream(stream)) => {
|
&HeapCellValue::Addr(addr) => {
|
||||||
|
if let Some(offset_str) = self.offset_as_string(iter, addr) {
|
||||||
|
push_space_if_amb!(self, &offset_str, {
|
||||||
|
self.append_str(offset_str.as_str());
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&HeapCellValue::Integer(ref n) => {
|
||||||
|
self.print_number(Number::Integer(n.clone()), &op);
|
||||||
|
}
|
||||||
|
&HeapCellValue::Rational(ref n) => {
|
||||||
|
self.print_number(Number::Rational(n.clone()), &op);
|
||||||
|
}
|
||||||
|
&HeapCellValue::PartialString(_)
|
||||||
|
if self.print_strings_as_strs => {
|
||||||
|
if let Addr::Con(h) = addr {
|
||||||
|
self.print_string_as_str(h, 0, true);
|
||||||
|
} else {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&HeapCellValue::PartialString(_) => {
|
||||||
|
if let Addr::Con(h) = addr {
|
||||||
|
self.print_string(max_depth, h, 0);
|
||||||
|
} else {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&HeapCellValue::Stream(ref stream) => {
|
||||||
if let Some(alias) = &stream.options.alias {
|
if let Some(alias) = &stream.options.alias {
|
||||||
self.print_atom(alias);
|
self.print_atom(alias);
|
||||||
} else {
|
} else {
|
||||||
@@ -1317,17 +1384,7 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
HeapCellValue::Addr(addr) => {
|
|
||||||
if let Some(offset_str) = self.offset_as_string(iter, addr) {
|
|
||||||
push_space_if_amb!(self, &offset_str, {
|
|
||||||
self.append_str(offset_str.as_str());
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => {
|
_ => {
|
||||||
// This is the partial string case. We never clone a partial string
|
|
||||||
// for printing purposes, so.. this.
|
|
||||||
unreachable!()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -63,11 +63,11 @@ impl CodeOffsets {
|
|||||||
let is_initial_index = self.lists.is_empty();
|
let is_initial_index = self.lists.is_empty();
|
||||||
self.lists.push(Self::add_index(is_initial_index, index));
|
self.lists.push(Self::add_index(is_initial_index, index));
|
||||||
}
|
}
|
||||||
&Term::Constant(_, Constant::String(n, ref s)) => {
|
&Term::Constant(_, Constant::String(ref s)) => {
|
||||||
let is_initial_index = self.lists.is_empty();
|
let is_initial_index = self.lists.is_empty();
|
||||||
self.lists.push(Self::add_index(is_initial_index, index));
|
self.lists.push(Self::add_index(is_initial_index, index));
|
||||||
|
|
||||||
let constant = Constant::String(n, s.clone());
|
let constant = Constant::String(s.clone());
|
||||||
let code = self.constants.entry(constant).or_insert(Vec::new());
|
let code = self.constants.entry(constant).or_insert(Vec::new());
|
||||||
|
|
||||||
let is_initial_index = code.is_empty();
|
let is_initial_index = code.is_empty();
|
||||||
@@ -75,9 +75,11 @@ impl CodeOffsets {
|
|||||||
}
|
}
|
||||||
&Term::Constant(_, ref constant) => {
|
&Term::Constant(_, ref constant) => {
|
||||||
if let Constant::Atom(ref name, _) = constant {
|
if let Constant::Atom(ref name, _) = constant {
|
||||||
if !name.as_str().is_empty() && name.as_str().chars().skip(1).next().is_none() {
|
if name.is_char() {
|
||||||
let c = name.as_str().chars().next().unwrap();
|
let c = name.as_str().chars().next().unwrap();
|
||||||
let code = self.constants.entry(Constant::Char(c)).or_insert(vec![]);
|
let code = self.constants
|
||||||
|
.entry(Constant::Char(c))
|
||||||
|
.or_insert(vec![]);
|
||||||
|
|
||||||
code.push(Self::add_index(code.is_empty(), index));
|
code.push(Self::add_index(code.is_empty(), index));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,28 +2,29 @@ use prolog_parser::ast::*;
|
|||||||
|
|
||||||
use crate::prolog::clause_types::*;
|
use crate::prolog::clause_types::*;
|
||||||
use crate::prolog::forms::*;
|
use crate::prolog::forms::*;
|
||||||
|
use crate::prolog::machine::heap::*;
|
||||||
use crate::prolog::machine::machine_errors::MachineStub;
|
use crate::prolog::machine::machine_errors::MachineStub;
|
||||||
use crate::prolog::machine::machine_indices::*;
|
use crate::prolog::machine::machine_indices::*;
|
||||||
|
|
||||||
use crate::prolog::rug::Integer;
|
use crate::prolog::rug::Integer;
|
||||||
|
|
||||||
use indexmap::IndexMap;
|
use indexmap::IndexMap;
|
||||||
|
|
||||||
use std::collections::VecDeque;
|
use std::collections::VecDeque;
|
||||||
|
use std::rc::Rc;
|
||||||
|
|
||||||
fn reg_type_into_functor(r: RegType) -> MachineStub {
|
fn reg_type_into_functor(r: RegType) -> MachineStub {
|
||||||
match r {
|
match r {
|
||||||
RegType::Temp(r) => functor!("x", 1, [heap_integer!(Integer::from(r))]),
|
RegType::Temp(r) => functor!("x", [integer(r)]),
|
||||||
RegType::Perm(r) => functor!("y", 1, [heap_integer!(Integer::from(r))]),
|
RegType::Perm(r) => functor!("y", [integer(r)]),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Level {
|
impl Level {
|
||||||
fn into_functor(self) -> MachineStub {
|
fn into_functor(self) -> MachineStub {
|
||||||
match self {
|
match self {
|
||||||
Level::Root => functor!("level", 1, [heap_atom!("root")]),
|
Level::Root => functor!("level", [atom("root")]),
|
||||||
Level::Shallow => functor!("level", 1, [heap_atom!("shallow")]),
|
Level::Shallow => functor!("level", [atom("shallow")]),
|
||||||
Level::Deep => functor!("level", 1, [heap_atom!("deep")]),
|
Level::Deep => functor!("level", [atom("deep")]),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -31,11 +32,15 @@ impl Level {
|
|||||||
impl ArithmeticTerm {
|
impl ArithmeticTerm {
|
||||||
fn into_functor(&self) -> MachineStub {
|
fn into_functor(&self) -> MachineStub {
|
||||||
match self {
|
match self {
|
||||||
&ArithmeticTerm::Reg(r) => reg_type_into_functor(r),
|
&ArithmeticTerm::Reg(r) => {
|
||||||
&ArithmeticTerm::Interm(i) => {
|
reg_type_into_functor(r)
|
||||||
functor!("intermediate", 1, [heap_integer!(Integer::from(i))])
|
}
|
||||||
|
&ArithmeticTerm::Interm(i) => {
|
||||||
|
functor!("intermediate", [integer(i)])
|
||||||
|
}
|
||||||
|
&ArithmeticTerm::Number(ref n) => {
|
||||||
|
vec![n.clone().into()]
|
||||||
}
|
}
|
||||||
&ArithmeticTerm::Number(ref n) => vec![heap_con!(n.clone().to_constant())],
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -52,18 +57,20 @@ impl ChoiceInstruction {
|
|||||||
pub fn to_functor(&self) -> MachineStub {
|
pub fn to_functor(&self) -> MachineStub {
|
||||||
match self {
|
match self {
|
||||||
&ChoiceInstruction::TryMeElse(offset) => {
|
&ChoiceInstruction::TryMeElse(offset) => {
|
||||||
functor!("try_me_else", 1, [heap_integer!(Integer::from(offset))])
|
functor!("try_me_else", [integer(offset)])
|
||||||
}
|
}
|
||||||
&ChoiceInstruction::RetryMeElse(offset) => {
|
&ChoiceInstruction::RetryMeElse(offset) => {
|
||||||
functor!("retry_me_else", 1, [heap_integer!(Integer::from(offset))])
|
functor!("retry_me_else", [integer(offset)])
|
||||||
|
}
|
||||||
|
&ChoiceInstruction::TrustMe => {
|
||||||
|
functor!("trust_me")
|
||||||
|
}
|
||||||
|
&ChoiceInstruction::DefaultRetryMeElse(offset) => {
|
||||||
|
functor!("default_retry_me_else", [integer(offset)])
|
||||||
|
}
|
||||||
|
&ChoiceInstruction::DefaultTrustMe => {
|
||||||
|
functor!("default_trust_me")
|
||||||
}
|
}
|
||||||
&ChoiceInstruction::TrustMe => vec![heap_atom!("trust_me")],
|
|
||||||
&ChoiceInstruction::DefaultRetryMeElse(offset) => functor!(
|
|
||||||
"default_retry_me_else",
|
|
||||||
1,
|
|
||||||
[heap_integer!(Integer::from(offset))]
|
|
||||||
),
|
|
||||||
&ChoiceInstruction::DefaultTrustMe => vec![heap_atom!("default_trust_me")],
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -79,21 +86,20 @@ impl CutInstruction {
|
|||||||
pub fn to_functor(&self, h: usize) -> MachineStub {
|
pub fn to_functor(&self, h: usize) -> MachineStub {
|
||||||
match self {
|
match self {
|
||||||
&CutInstruction::Cut(r) => {
|
&CutInstruction::Cut(r) => {
|
||||||
let mut stub = functor!("cut", 1, [heap_str!(h + 2)]);
|
let rt_stub = reg_type_into_functor(r);
|
||||||
stub.append(&mut reg_type_into_functor(r));
|
functor!("cut", [aux(h, 0)], [rt_stub])
|
||||||
stub
|
|
||||||
}
|
}
|
||||||
&CutInstruction::GetLevel(r) => {
|
&CutInstruction::GetLevel(r) => {
|
||||||
let mut stub = functor!("get_level", 1, [heap_str!(h + 2)]);
|
let rt_stub = reg_type_into_functor(r);
|
||||||
stub.append(&mut reg_type_into_functor(r));
|
functor!("get_level", [aux(h, 0)], [rt_stub])
|
||||||
stub
|
|
||||||
}
|
}
|
||||||
&CutInstruction::GetLevelAndUnify(r) => {
|
&CutInstruction::GetLevelAndUnify(r) => {
|
||||||
let mut stub = functor!("get_level_and_unify", 1, [heap_str!(h + 2)]);
|
let rt_stub = reg_type_into_functor(r);
|
||||||
stub.append(&mut reg_type_into_functor(r));
|
functor!("get_level_and_unify", [aux(h, 0)], [rt_stub])
|
||||||
stub
|
}
|
||||||
|
&CutInstruction::NeckCut => {
|
||||||
|
functor!("neck_cut")
|
||||||
}
|
}
|
||||||
&CutInstruction::NeckCut => vec![heap_atom!("neck_cut")],
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -122,13 +128,13 @@ impl IndexedChoiceInstruction {
|
|||||||
pub fn to_functor(&self) -> MachineStub {
|
pub fn to_functor(&self) -> MachineStub {
|
||||||
match self {
|
match self {
|
||||||
&IndexedChoiceInstruction::Try(offset) => {
|
&IndexedChoiceInstruction::Try(offset) => {
|
||||||
functor!("try", 1, [heap_integer!(Integer::from(offset))])
|
functor!("try", [integer(offset)])
|
||||||
}
|
}
|
||||||
&IndexedChoiceInstruction::Trust(offset) => {
|
&IndexedChoiceInstruction::Trust(offset) => {
|
||||||
functor!("trust", 1, [heap_integer!(Integer::from(offset))])
|
functor!("trust", [integer(offset)])
|
||||||
}
|
}
|
||||||
&IndexedChoiceInstruction::Retry(offset) => {
|
&IndexedChoiceInstruction::Retry(offset) => {
|
||||||
functor!("retry", 1, [heap_integer!(Integer::from(offset))])
|
functor!("retry", [integer(offset)])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -219,15 +225,12 @@ fn arith_instr_unary_functor(
|
|||||||
t: usize,
|
t: usize,
|
||||||
) -> MachineStub {
|
) -> MachineStub {
|
||||||
let at_stub = at.into_functor();
|
let at_stub = at.into_functor();
|
||||||
|
|
||||||
let mut stub = functor!(
|
functor!(
|
||||||
name,
|
name,
|
||||||
2,
|
[aux(h, 0), integer(t)],
|
||||||
[heap_cell!(h + 4), heap_integer!(Integer::from(t))]
|
[at_stub]
|
||||||
);
|
)
|
||||||
|
|
||||||
stub.extend(at_stub.into_iter());
|
|
||||||
stub
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn arith_instr_bin_functor(
|
fn arith_instr_bin_functor(
|
||||||
@@ -240,20 +243,11 @@ fn arith_instr_bin_functor(
|
|||||||
let at_1_stub = at_1.into_functor();
|
let at_1_stub = at_1.into_functor();
|
||||||
let at_2_stub = at_2.into_functor();
|
let at_2_stub = at_2.into_functor();
|
||||||
|
|
||||||
let mut stub = functor!(
|
functor!(
|
||||||
name,
|
name,
|
||||||
3,
|
[aux(h, 0), aux(h, 1), integer(t)],
|
||||||
[
|
[at_1_stub, at_2_stub]
|
||||||
heap_cell!(h + 4),
|
)
|
||||||
heap_cell!(h + 4 + at_1_stub.len()),
|
|
||||||
heap_integer!(Integer::from(t))
|
|
||||||
]
|
|
||||||
);
|
|
||||||
|
|
||||||
stub.extend(at_1_stub.into_iter());
|
|
||||||
stub.extend(at_2_stub.into_iter());
|
|
||||||
|
|
||||||
stub
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ArithmeticInstruction {
|
impl ArithmeticInstruction {
|
||||||
@@ -319,17 +313,39 @@ impl ArithmeticInstruction {
|
|||||||
&ArithmeticInstruction::Gcd(ref at_1, ref at_2, t) => {
|
&ArithmeticInstruction::Gcd(ref at_1, ref at_2, t) => {
|
||||||
arith_instr_bin_functor(h, "gcd", at_1, at_2, t)
|
arith_instr_bin_functor(h, "gcd", at_1, at_2, t)
|
||||||
}
|
}
|
||||||
&ArithmeticInstruction::Sign(ref at, t) => arith_instr_unary_functor(h, "sign", at, t),
|
&ArithmeticInstruction::Sign(ref at, t) => {
|
||||||
&ArithmeticInstruction::Cos(ref at, t) => arith_instr_unary_functor(h, "cos", at, t),
|
arith_instr_unary_functor(h, "sign", at, t)
|
||||||
&ArithmeticInstruction::Sin(ref at, t) => arith_instr_unary_functor(h, "sin", at, t),
|
}
|
||||||
&ArithmeticInstruction::Tan(ref at, t) => arith_instr_unary_functor(h, "tan", at, t),
|
&ArithmeticInstruction::Cos(ref at, t) => {
|
||||||
&ArithmeticInstruction::Log(ref at, t) => arith_instr_unary_functor(h, "log", at, t),
|
arith_instr_unary_functor(h, "cos", at, t)
|
||||||
&ArithmeticInstruction::Exp(ref at, t) => arith_instr_unary_functor(h, "exp", at, t),
|
}
|
||||||
&ArithmeticInstruction::ACos(ref at, t) => arith_instr_unary_functor(h, "acos", at, t),
|
&ArithmeticInstruction::Sin(ref at, t) => {
|
||||||
&ArithmeticInstruction::ASin(ref at, t) => arith_instr_unary_functor(h, "asin", at, t),
|
arith_instr_unary_functor(h, "sin", at, t)
|
||||||
&ArithmeticInstruction::ATan(ref at, t) => arith_instr_unary_functor(h, "atan", at, t),
|
}
|
||||||
&ArithmeticInstruction::Sqrt(ref at, t) => arith_instr_unary_functor(h, "sqrt", at, t),
|
&ArithmeticInstruction::Tan(ref at, t) => {
|
||||||
&ArithmeticInstruction::Abs(ref at, t) => arith_instr_unary_functor(h, "abs", at, t),
|
arith_instr_unary_functor(h, "tan", at, t)
|
||||||
|
}
|
||||||
|
&ArithmeticInstruction::Log(ref at, t) => {
|
||||||
|
arith_instr_unary_functor(h, "log", at, t)
|
||||||
|
}
|
||||||
|
&ArithmeticInstruction::Exp(ref at, t) => {
|
||||||
|
arith_instr_unary_functor(h, "exp", at, t)
|
||||||
|
}
|
||||||
|
&ArithmeticInstruction::ACos(ref at, t) => {
|
||||||
|
arith_instr_unary_functor(h, "acos", at, t)
|
||||||
|
}
|
||||||
|
&ArithmeticInstruction::ASin(ref at, t) => {
|
||||||
|
arith_instr_unary_functor(h, "asin", at, t)
|
||||||
|
}
|
||||||
|
&ArithmeticInstruction::ATan(ref at, t) => {
|
||||||
|
arith_instr_unary_functor(h, "atan", at, t)
|
||||||
|
}
|
||||||
|
&ArithmeticInstruction::Sqrt(ref at, t) => {
|
||||||
|
arith_instr_unary_functor(h, "sqrt", at, t)
|
||||||
|
}
|
||||||
|
&ArithmeticInstruction::Abs(ref at, t) => {
|
||||||
|
arith_instr_unary_functor(h, "abs", at, t)
|
||||||
|
}
|
||||||
&ArithmeticInstruction::Float(ref at, t) => {
|
&ArithmeticInstruction::Float(ref at, t) => {
|
||||||
arith_instr_unary_functor(h, "float", at, t)
|
arith_instr_unary_functor(h, "float", at, t)
|
||||||
}
|
}
|
||||||
@@ -345,8 +361,12 @@ impl ArithmeticInstruction {
|
|||||||
&ArithmeticInstruction::Floor(ref at, t) => {
|
&ArithmeticInstruction::Floor(ref at, t) => {
|
||||||
arith_instr_unary_functor(h, "floor", at, t)
|
arith_instr_unary_functor(h, "floor", at, t)
|
||||||
}
|
}
|
||||||
&ArithmeticInstruction::Neg(ref at, t) => arith_instr_unary_functor(h, "-", at, t),
|
&ArithmeticInstruction::Neg(ref at, t) => {
|
||||||
&ArithmeticInstruction::Plus(ref at, t) => arith_instr_unary_functor(h, "+", at, t),
|
arith_instr_unary_functor(h, "-", at, t)
|
||||||
|
}
|
||||||
|
&ArithmeticInstruction::Plus(ref at, t) => {
|
||||||
|
arith_instr_unary_functor(h, "+", at, t)
|
||||||
|
}
|
||||||
&ArithmeticInstruction::BitwiseComplement(ref at, t) => {
|
&ArithmeticInstruction::BitwiseComplement(ref at, t) => {
|
||||||
arith_instr_unary_functor(h, "\\", at, t)
|
arith_instr_unary_functor(h, "\\", at, t)
|
||||||
}
|
}
|
||||||
@@ -378,29 +398,23 @@ impl ControlInstruction {
|
|||||||
pub fn to_functor(&self) -> MachineStub {
|
pub fn to_functor(&self) -> MachineStub {
|
||||||
match self {
|
match self {
|
||||||
&ControlInstruction::Allocate(num_frames) => {
|
&ControlInstruction::Allocate(num_frames) => {
|
||||||
functor!("allocate", 1, [heap_integer!(Integer::from(num_frames))])
|
functor!("allocate", [integer(num_frames)])
|
||||||
|
}
|
||||||
|
&ControlInstruction::CallClause(ref ct, arity, _, false, _) => {
|
||||||
|
functor!("call", [clause_name(ct.name()), integer(arity)])
|
||||||
|
}
|
||||||
|
&ControlInstruction::CallClause(ref ct, arity, _, true, _) => {
|
||||||
|
functor!("execute", [clause_name(ct.name()), integer(arity)])
|
||||||
|
}
|
||||||
|
&ControlInstruction::Deallocate => {
|
||||||
|
functor!("deallocate")
|
||||||
}
|
}
|
||||||
&ControlInstruction::CallClause(ref ct, arity, _, false, _) => functor!(
|
|
||||||
"call",
|
|
||||||
2,
|
|
||||||
[
|
|
||||||
heap_con!(Constant::Atom(ct.name(), None)),
|
|
||||||
heap_integer!(Integer::from(arity))
|
|
||||||
]
|
|
||||||
),
|
|
||||||
&ControlInstruction::CallClause(ref ct, arity, _, true, _) => functor!(
|
|
||||||
"execute",
|
|
||||||
2,
|
|
||||||
[
|
|
||||||
heap_con!(Constant::Atom(ct.name(), None)),
|
|
||||||
heap_integer!(Integer::from(arity))
|
|
||||||
]
|
|
||||||
),
|
|
||||||
&ControlInstruction::Deallocate => vec![heap_atom!("deallocate")],
|
|
||||||
&ControlInstruction::JmpBy(_, offset, ..) => {
|
&ControlInstruction::JmpBy(_, offset, ..) => {
|
||||||
functor!("jmp_by", 1, [heap_integer!(Integer::from(offset))])
|
functor!("jmp_by", [integer(offset)])
|
||||||
|
}
|
||||||
|
&ControlInstruction::Proceed => {
|
||||||
|
functor!("proceed")
|
||||||
}
|
}
|
||||||
&ControlInstruction::Proceed => vec![heap_atom!("proceed")],
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -420,26 +434,27 @@ impl From<IndexingInstruction> for Line {
|
|||||||
impl IndexingInstruction {
|
impl IndexingInstruction {
|
||||||
pub fn to_functor(&self) -> MachineStub {
|
pub fn to_functor(&self) -> MachineStub {
|
||||||
match self {
|
match self {
|
||||||
&IndexingInstruction::SwitchOnTerm(vars, constants, lists, structures) => functor!(
|
&IndexingInstruction::SwitchOnTerm(vars, constants, lists, structures) => {
|
||||||
"switch_on_term",
|
functor!(
|
||||||
4,
|
"switch_on_term",
|
||||||
[
|
[integer(vars),
|
||||||
heap_integer!(Integer::from(vars)),
|
integer(constants),
|
||||||
heap_integer!(Integer::from(constants)),
|
integer(lists),
|
||||||
heap_integer!(Integer::from(lists)),
|
integer(structures)]
|
||||||
heap_integer!(Integer::from(structures))
|
)
|
||||||
]
|
}
|
||||||
),
|
&IndexingInstruction::SwitchOnConstant(constants, _) => {
|
||||||
&IndexingInstruction::SwitchOnConstant(constants, _) => functor!(
|
functor!(
|
||||||
"switch_on_constant",
|
"switch_on_constant",
|
||||||
1,
|
[integer(constants)]
|
||||||
[heap_integer!(Integer::from(constants))]
|
)
|
||||||
),
|
}
|
||||||
&IndexingInstruction::SwitchOnStructure(structures, _) => functor!(
|
&IndexingInstruction::SwitchOnStructure(structures, _) => {
|
||||||
"switch_on_structure",
|
functor!(
|
||||||
1,
|
"switch_on_structure",
|
||||||
[heap_integer!(Integer::from(structures))]
|
[integer(structures)]
|
||||||
),
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -461,86 +476,85 @@ pub enum FactInstruction {
|
|||||||
impl FactInstruction {
|
impl FactInstruction {
|
||||||
pub fn to_functor(&self, h: usize) -> MachineStub {
|
pub fn to_functor(&self, h: usize) -> MachineStub {
|
||||||
match self {
|
match self {
|
||||||
&FactInstruction::GetConstant(lvl, ref constant, r) => {
|
&FactInstruction::GetConstant(lvl, ref c, r) => {
|
||||||
let mut stub = functor!(
|
let lvl_stub = lvl.into_functor();
|
||||||
|
let rt_stub = reg_type_into_functor(r);
|
||||||
|
|
||||||
|
functor!(
|
||||||
"get_constant",
|
"get_constant",
|
||||||
3,
|
[aux(h, 0), constant(c), aux(h, 1)],
|
||||||
[
|
[lvl_stub, rt_stub]
|
||||||
heap_str!(h + 4),
|
)
|
||||||
heap_con!(constant.clone()),
|
|
||||||
heap_str!(h + 6)
|
|
||||||
]
|
|
||||||
);
|
|
||||||
|
|
||||||
stub.append(&mut lvl.into_functor());
|
|
||||||
stub.append(&mut reg_type_into_functor(r));
|
|
||||||
|
|
||||||
stub
|
|
||||||
}
|
}
|
||||||
&FactInstruction::GetList(lvl, r) => {
|
&FactInstruction::GetList(lvl, r) => {
|
||||||
let mut stub = functor!("get_list", 2, [heap_str!(h + 3), heap_str!(h + 5)]);
|
let lvl_stub = lvl.into_functor();
|
||||||
stub.append(&mut lvl.into_functor());
|
let rt_stub = reg_type_into_functor(r);
|
||||||
stub.append(&mut reg_type_into_functor(r));
|
|
||||||
|
|
||||||
stub
|
functor!(
|
||||||
|
"get_list",
|
||||||
|
[aux(h, 0), aux(h, 1)],
|
||||||
|
[lvl_stub, rt_stub]
|
||||||
|
)
|
||||||
}
|
}
|
||||||
&FactInstruction::GetStructure(ref ct, arity, r) => {
|
&FactInstruction::GetStructure(ref ct, arity, r) => {
|
||||||
let mut stub = functor!(
|
let rt_stub = reg_type_into_functor(r);
|
||||||
"get_structure",
|
|
||||||
3,
|
|
||||||
[
|
|
||||||
heap_con!(Constant::Atom(ct.name(), None)),
|
|
||||||
heap_integer!(Integer::from(arity)),
|
|
||||||
heap_str!(h + 4)
|
|
||||||
]
|
|
||||||
);
|
|
||||||
stub.append(&mut reg_type_into_functor(r));
|
|
||||||
|
|
||||||
stub
|
functor!(
|
||||||
|
"get_structure",
|
||||||
|
[clause_name(ct.name()), integer(arity), aux(h, 0)],
|
||||||
|
[rt_stub]
|
||||||
|
)
|
||||||
}
|
}
|
||||||
&FactInstruction::GetValue(r, arg) => {
|
&FactInstruction::GetValue(r, arg) => {
|
||||||
let mut stub = functor!(
|
let rt_stub = reg_type_into_functor(r);
|
||||||
"get_value",
|
|
||||||
2,
|
|
||||||
[heap_str!(h + 3), heap_integer!(Integer::from(arg))]
|
|
||||||
);
|
|
||||||
stub.append(&mut reg_type_into_functor(r));
|
|
||||||
|
|
||||||
stub
|
functor!(
|
||||||
|
"get_value",
|
||||||
|
[aux(h, 0), integer(arg)],
|
||||||
|
[rt_stub]
|
||||||
|
)
|
||||||
}
|
}
|
||||||
&FactInstruction::GetVariable(r, arg) => {
|
&FactInstruction::GetVariable(r, arg) => {
|
||||||
let mut stub = functor!(
|
let rt_stub = reg_type_into_functor(r);
|
||||||
"get_variable",
|
|
||||||
2,
|
|
||||||
[heap_str!(h + 3), heap_integer!(Integer::from(arg))]
|
|
||||||
);
|
|
||||||
stub.append(&mut reg_type_into_functor(r));
|
|
||||||
|
|
||||||
stub
|
functor!(
|
||||||
|
"get_variable",
|
||||||
|
[aux(h, 0), integer(arg)],
|
||||||
|
[rt_stub]
|
||||||
|
)
|
||||||
}
|
}
|
||||||
&FactInstruction::UnifyConstant(ref constant) => {
|
&FactInstruction::UnifyConstant(ref c) => {
|
||||||
functor!("unify_constant", 1, [heap_con!(constant.clone())])
|
functor!("unify_constant", [constant(c)], [])
|
||||||
}
|
}
|
||||||
&FactInstruction::UnifyLocalValue(r) => {
|
&FactInstruction::UnifyLocalValue(r) => {
|
||||||
let mut stub = functor!("unify_local_value", 1, [heap_str!(h + 2)]);
|
let rt_stub = reg_type_into_functor(r);
|
||||||
stub.append(&mut reg_type_into_functor(r));
|
|
||||||
|
functor!(
|
||||||
stub
|
"unify_local_value",
|
||||||
|
[aux(h, 0)],
|
||||||
|
[rt_stub]
|
||||||
|
)
|
||||||
}
|
}
|
||||||
&FactInstruction::UnifyVariable(r) => {
|
&FactInstruction::UnifyVariable(r) => {
|
||||||
let mut stub = functor!("unify_variable", 1, [heap_str!(h + 2)]);
|
let rt_stub = reg_type_into_functor(r);
|
||||||
stub.append(&mut reg_type_into_functor(r));
|
|
||||||
|
|
||||||
stub
|
functor!(
|
||||||
|
"unify_variable",
|
||||||
|
[aux(h, 0)],
|
||||||
|
[rt_stub]
|
||||||
|
)
|
||||||
}
|
}
|
||||||
&FactInstruction::UnifyValue(r) => {
|
&FactInstruction::UnifyValue(r) => {
|
||||||
let mut stub = functor!("unify_value", 1, [heap_str!(h + 2)]);
|
let rt_stub = reg_type_into_functor(r);
|
||||||
stub.append(&mut reg_type_into_functor(r));
|
|
||||||
|
functor!(
|
||||||
stub
|
"unify_value",
|
||||||
|
[aux(h, 0)],
|
||||||
|
[rt_stub]
|
||||||
|
)
|
||||||
}
|
}
|
||||||
&FactInstruction::UnifyVoid(vars) => {
|
&FactInstruction::UnifyVoid(vars) => {
|
||||||
functor!("unify_void", 1, [heap_integer!(Integer::from(vars))])
|
functor!("unify_void", [integer(vars)])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -567,103 +581,96 @@ impl QueryInstruction {
|
|||||||
match self {
|
match self {
|
||||||
&QueryInstruction::PutUnsafeValue(norm, arg) => functor!(
|
&QueryInstruction::PutUnsafeValue(norm, arg) => functor!(
|
||||||
"put_unsafe_value",
|
"put_unsafe_value",
|
||||||
2,
|
[integer(norm), integer(arg)]
|
||||||
[
|
|
||||||
heap_integer!(Integer::from(norm)),
|
|
||||||
heap_integer!(Integer::from(arg))
|
|
||||||
]
|
|
||||||
),
|
),
|
||||||
&QueryInstruction::PutConstant(lvl, ref constant, r) => {
|
&QueryInstruction::PutConstant(lvl, ref c, r) => {
|
||||||
let mut stub = functor!(
|
let lvl_stub = lvl.into_functor();
|
||||||
|
let rt_stub = reg_type_into_functor(r);
|
||||||
|
|
||||||
|
functor!(
|
||||||
"put_constant",
|
"put_constant",
|
||||||
3,
|
[aux(h, 0), constant(c), aux(h, 1)],
|
||||||
[
|
[lvl_stub, rt_stub]
|
||||||
heap_str!(h + 4),
|
)
|
||||||
heap_con!(constant.clone()),
|
|
||||||
heap_str!(h + 6)
|
|
||||||
]
|
|
||||||
);
|
|
||||||
|
|
||||||
stub.append(&mut lvl.into_functor());
|
|
||||||
stub.append(&mut reg_type_into_functor(r));
|
|
||||||
|
|
||||||
stub
|
|
||||||
}
|
}
|
||||||
&QueryInstruction::PutList(lvl, r) => {
|
&QueryInstruction::PutList(lvl, r) => {
|
||||||
let mut stub = functor!("put_list", 2, [heap_str!(h + 3), heap_str!(h + 5)]);
|
let lvl_stub = lvl.into_functor();
|
||||||
|
let rt_stub = reg_type_into_functor(r);
|
||||||
stub.append(&mut lvl.into_functor());
|
|
||||||
stub.append(&mut reg_type_into_functor(r));
|
functor!(
|
||||||
|
"put_list",
|
||||||
stub
|
[aux(h, 0), aux(h, 1)],
|
||||||
|
[lvl_stub, rt_stub]
|
||||||
|
)
|
||||||
}
|
}
|
||||||
&QueryInstruction::PutStructure(ref ct, arity, r) => {
|
&QueryInstruction::PutStructure(ref ct, arity, r) => {
|
||||||
let mut stub = functor!(
|
let rt_stub = reg_type_into_functor(r);
|
||||||
"put_structure",
|
|
||||||
3,
|
|
||||||
[
|
|
||||||
heap_con!(Constant::Atom(ct.name(), None)),
|
|
||||||
heap_integer!(Integer::from(arity)),
|
|
||||||
heap_str!(h + 4)
|
|
||||||
]
|
|
||||||
);
|
|
||||||
|
|
||||||
stub.append(&mut reg_type_into_functor(r));
|
functor!(
|
||||||
stub
|
"put_structure",
|
||||||
|
[clause_name(ct.name()), integer(arity), aux(h, 0)],
|
||||||
|
[rt_stub]
|
||||||
|
)
|
||||||
}
|
}
|
||||||
&QueryInstruction::PutValue(r, arg) => {
|
&QueryInstruction::PutValue(r, arg) => {
|
||||||
let mut stub = functor!(
|
let rt_stub = reg_type_into_functor(r);
|
||||||
"put_value",
|
|
||||||
2,
|
|
||||||
[heap_str!(h + 3), heap_integer!(Integer::from(arg))]
|
|
||||||
);
|
|
||||||
|
|
||||||
stub.append(&mut reg_type_into_functor(r));
|
functor!(
|
||||||
stub
|
"put_value",
|
||||||
|
[aux(h, 0), integer(arg)],
|
||||||
|
[rt_stub]
|
||||||
|
)
|
||||||
}
|
}
|
||||||
&QueryInstruction::GetVariable(r, arg) => {
|
&QueryInstruction::GetVariable(r, arg) => {
|
||||||
let mut stub = functor!(
|
let rt_stub = reg_type_into_functor(r);
|
||||||
"get_variable",
|
|
||||||
2,
|
|
||||||
[heap_str!(h + 3), heap_integer!(Integer::from(arg))]
|
|
||||||
);
|
|
||||||
|
|
||||||
stub.append(&mut reg_type_into_functor(r));
|
functor!(
|
||||||
stub
|
"get_variable",
|
||||||
|
[aux(h, 0), integer(arg)],
|
||||||
|
[rt_stub]
|
||||||
|
)
|
||||||
}
|
}
|
||||||
&QueryInstruction::PutVariable(r, arg) => {
|
&QueryInstruction::PutVariable(r, arg) => {
|
||||||
let mut stub = functor!(
|
let rt_stub = reg_type_into_functor(r);
|
||||||
"put_variable",
|
|
||||||
2,
|
|
||||||
[heap_str!(h + 3), heap_integer!(Integer::from(arg))]
|
|
||||||
);
|
|
||||||
|
|
||||||
stub.append(&mut reg_type_into_functor(r));
|
functor!(
|
||||||
stub
|
"put_variable",
|
||||||
|
[aux(h, 0), integer(arg)],
|
||||||
|
[rt_stub]
|
||||||
|
)
|
||||||
}
|
}
|
||||||
&QueryInstruction::SetConstant(ref constant) => {
|
&QueryInstruction::SetConstant(ref c) => {
|
||||||
functor!("set_constant", 1, [heap_con!(constant.clone())])
|
functor!("set_constant", [constant(c)], [])
|
||||||
}
|
}
|
||||||
&QueryInstruction::SetLocalValue(r) => {
|
&QueryInstruction::SetLocalValue(r) => {
|
||||||
let mut stub = functor!("set_local_value", 1, [heap_str!(h + 2)]);
|
let rt_stub = reg_type_into_functor(r);
|
||||||
|
|
||||||
stub.append(&mut reg_type_into_functor(r));
|
functor!(
|
||||||
stub
|
"set_local_value",
|
||||||
|
[aux(h, 0)],
|
||||||
|
[rt_stub]
|
||||||
|
)
|
||||||
}
|
}
|
||||||
&QueryInstruction::SetVariable(r) => {
|
&QueryInstruction::SetVariable(r) => {
|
||||||
let mut stub = functor!("set_variable", 1, [heap_str!(h + 2)]);
|
let rt_stub = reg_type_into_functor(r);
|
||||||
|
|
||||||
stub.append(&mut reg_type_into_functor(r));
|
functor!(
|
||||||
stub
|
"set_variable",
|
||||||
|
[aux(h, 0)],
|
||||||
|
[rt_stub]
|
||||||
|
)
|
||||||
}
|
}
|
||||||
&QueryInstruction::SetValue(r) => {
|
&QueryInstruction::SetValue(r) => {
|
||||||
let mut stub = functor!("set_value", 1, [heap_str!(h + 2)]);
|
let rt_stub = reg_type_into_functor(r);
|
||||||
|
|
||||||
stub.append(&mut reg_type_into_functor(r));
|
functor!(
|
||||||
stub
|
"set_value",
|
||||||
|
[aux(h, 0)],
|
||||||
|
[rt_stub]
|
||||||
|
)
|
||||||
}
|
}
|
||||||
&QueryInstruction::SetVoid(vars) => {
|
&QueryInstruction::SetVoid(vars) => {
|
||||||
functor!("set_void", 1, [heap_integer!(Integer::from(vars))])
|
functor!("set_void", [integer(vars)])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
786
src/prolog/machine/arithmetic_ops.rs
Normal file
786
src/prolog/machine/arithmetic_ops.rs
Normal file
@@ -0,0 +1,786 @@
|
|||||||
|
use crate::prolog_parser::ast::*;
|
||||||
|
|
||||||
|
use crate::prolog::arithmetic::*;
|
||||||
|
use crate::prolog::clause_types::*;
|
||||||
|
use crate::prolog::forms::*;
|
||||||
|
use crate::prolog::machine::machine_errors::*;
|
||||||
|
use crate::prolog::machine::machine_indices::*;
|
||||||
|
use crate::prolog::machine::machine_state::*;
|
||||||
|
use crate::prolog::ordered_float::*;
|
||||||
|
use crate::prolog::rug::{Integer, Rational};
|
||||||
|
|
||||||
|
use std::cmp;
|
||||||
|
use std::f64;
|
||||||
|
use std::mem;
|
||||||
|
use std::rc::Rc;
|
||||||
|
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! try_numeric_result {
|
||||||
|
($s: ident, $e: expr, $caller: expr) => (
|
||||||
|
match $e {
|
||||||
|
Ok(val) => {
|
||||||
|
Ok(val)
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
let caller_copy =
|
||||||
|
$caller.iter().map(|v| v.context_free_clone()).collect();
|
||||||
|
|
||||||
|
Err($s.error_form(MachineError::evaluation_error(e), caller_copy))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MachineState {
|
||||||
|
pub(crate)
|
||||||
|
fn get_number(&mut self, at: &ArithmeticTerm) -> Result<Number, MachineStub> {
|
||||||
|
match at {
|
||||||
|
&ArithmeticTerm::Reg(r) => {
|
||||||
|
self.arith_eval_by_metacall(r)
|
||||||
|
}
|
||||||
|
&ArithmeticTerm::Interm(i) => Ok(mem::replace(
|
||||||
|
&mut self.interms[i - 1],
|
||||||
|
Number::Integer(Rc::new(Integer::from(0))),
|
||||||
|
)),
|
||||||
|
&ArithmeticTerm::Number(ref n) => {
|
||||||
|
Ok(n.clone())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(super)
|
||||||
|
fn rational_from_number(
|
||||||
|
&self,
|
||||||
|
n: Number,
|
||||||
|
) -> Result<Rc<Rational>, MachineError> {
|
||||||
|
match n {
|
||||||
|
Number::Rational(r) => {
|
||||||
|
Ok(r)
|
||||||
|
}
|
||||||
|
Number::Float(OrderedFloat(f)) => {
|
||||||
|
match Rational::from_f64(f) {
|
||||||
|
Some(r) => {
|
||||||
|
Ok(Rc::new(r))
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
Err(MachineError::instantiation_error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Number::Integer(n) => {
|
||||||
|
Ok(Rc::new(Rational::from(&*n)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate)
|
||||||
|
fn get_rational(
|
||||||
|
&mut self,
|
||||||
|
at: &ArithmeticTerm,
|
||||||
|
caller: MachineStub,
|
||||||
|
) -> Result<(Rc<Rational>, MachineStub), MachineStub> {
|
||||||
|
let n = self.get_number(at)?;
|
||||||
|
|
||||||
|
match self.rational_from_number(n) {
|
||||||
|
Ok(r) => Ok((r, caller)),
|
||||||
|
Err(e) => Err(self.error_form(e, caller))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate)
|
||||||
|
fn arith_eval_by_metacall(&self, r: RegType) -> Result<Number, MachineStub> {
|
||||||
|
let a = self[r].clone();
|
||||||
|
|
||||||
|
let caller = MachineError::functor_stub(clause_name!("(is)"), 2);
|
||||||
|
let mut interms: Vec<Number> = Vec::with_capacity(64);
|
||||||
|
|
||||||
|
for addr in self.post_order_iter(a) {
|
||||||
|
match self.heap.index_addr(&addr).as_ref() {
|
||||||
|
&HeapCellValue::NamedStr(2, ref name, _) => {
|
||||||
|
let a2 = interms.pop().unwrap();
|
||||||
|
let a1 = interms.pop().unwrap();
|
||||||
|
|
||||||
|
match name.as_str() {
|
||||||
|
"+" => interms.push(try_numeric_result!(self, a1 + a2, caller)?),
|
||||||
|
"-" => interms.push(try_numeric_result!(self, a1 - a2, caller)?),
|
||||||
|
"*" => interms.push(try_numeric_result!(self, a1 * a2, caller)?),
|
||||||
|
"/" => interms.push(self.div(a1, a2)?),
|
||||||
|
"**" => interms.push(self.pow(a1, a2, "(is)")?),
|
||||||
|
"^" => interms.push(self.int_pow(a1, a2)?),
|
||||||
|
"max" => interms.push(self.max(a1, a2)?),
|
||||||
|
"min" => interms.push(self.min(a1, a2)?),
|
||||||
|
"rdiv" => {
|
||||||
|
let r1 = self.rational_from_number(a1);
|
||||||
|
let r2 = r1.and_then(|r1| {
|
||||||
|
self.rational_from_number(a2).map(|r2| (r1, r2))
|
||||||
|
});
|
||||||
|
|
||||||
|
match r2 {
|
||||||
|
Ok((r1, r2)) => {
|
||||||
|
let result = Number::Rational(Rc::new(self.rdiv(r1, r2)?));
|
||||||
|
interms.push(result);
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
return Err(self.error_form(e, caller));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"//" => interms.push(Number::Integer(Rc::new(self.idiv(a1, a2)?))),
|
||||||
|
"div" => interms.push(Number::Integer(Rc::new(self.int_floor_div(a1, a2)?))),
|
||||||
|
">>" => interms.push(Number::Integer(Rc::new(self.shr(a1, a2)?))),
|
||||||
|
"<<" => interms.push(Number::Integer(Rc::new(self.shl(a1, a2)?))),
|
||||||
|
"/\\" => interms.push(Number::Integer(Rc::new(self.and(a1, a2)?))),
|
||||||
|
"\\/" => interms.push(Number::Integer(Rc::new(self.or(a1, a2)?))),
|
||||||
|
"xor" => interms.push(Number::Integer(Rc::new(self.xor(a1, a2)?))),
|
||||||
|
"mod" => interms.push(Number::Integer(Rc::new(self.modulus(a1, a2)?))),
|
||||||
|
"rem" => interms.push(Number::Integer(Rc::new(self.remainder(a1, a2)?))),
|
||||||
|
"atan2" => interms.push(Number::Float(OrderedFloat(self.atan2(a1, a2)?))),
|
||||||
|
"gcd" => interms.push(Number::Integer(Rc::new(self.gcd(a1, a2)?))),
|
||||||
|
_ => {
|
||||||
|
return Err(self.error_form(MachineError::instantiation_error(), caller))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&HeapCellValue::NamedStr(1, ref name, _) => {
|
||||||
|
let a1 = interms.pop().unwrap();
|
||||||
|
|
||||||
|
match name.as_str() {
|
||||||
|
"-" => interms.push(-a1),
|
||||||
|
"+" => interms.push(a1),
|
||||||
|
"cos" => interms.push(Number::Float(OrderedFloat(self.cos(a1)?))),
|
||||||
|
"sin" => interms.push(Number::Float(OrderedFloat(self.sin(a1)?))),
|
||||||
|
"tan" => interms.push(Number::Float(OrderedFloat(self.tan(a1)?))),
|
||||||
|
"sqrt" => interms.push(Number::Float(OrderedFloat(self.sqrt(a1)?))),
|
||||||
|
"log" => interms.push(Number::Float(OrderedFloat(self.log(a1)?))),
|
||||||
|
"exp" => interms.push(Number::Float(OrderedFloat(self.exp(a1)?))),
|
||||||
|
"acos" => interms.push(Number::Float(OrderedFloat(self.acos(a1)?))),
|
||||||
|
"asin" => interms.push(Number::Float(OrderedFloat(self.asin(a1)?))),
|
||||||
|
"atan" => interms.push(Number::Float(OrderedFloat(self.atan(a1)?))),
|
||||||
|
"abs" => interms.push(a1.abs()),
|
||||||
|
"float" => interms.push(Number::Float(OrderedFloat(self.float(a1)?))),
|
||||||
|
"truncate" => interms.push(Number::Integer(Rc::new(self.truncate(a1)))),
|
||||||
|
"round" => interms.push(Number::Integer(Rc::new(self.round(a1)?))),
|
||||||
|
"ceiling" => interms.push(Number::Integer(Rc::new(self.ceiling(a1)))),
|
||||||
|
"floor" => interms.push(Number::Integer(Rc::new(self.floor(a1)))),
|
||||||
|
"\\" => interms.push(Number::Integer(Rc::new(self.bitwise_complement(a1)?))),
|
||||||
|
"sign" => interms.push(Number::Integer(Rc::new(self.sign(a1)))),
|
||||||
|
_ => {
|
||||||
|
return Err(self.error_form(MachineError::instantiation_error(), caller));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&HeapCellValue::Integer(ref n) => {
|
||||||
|
interms.push(Number::Integer(n.clone()))
|
||||||
|
}
|
||||||
|
&HeapCellValue::Addr(Addr::Float(n)) => {
|
||||||
|
interms.push(Number::Float(n))
|
||||||
|
}
|
||||||
|
&HeapCellValue::Rational(ref n) => {
|
||||||
|
interms.push(Number::Rational(n.clone()))
|
||||||
|
}
|
||||||
|
&HeapCellValue::Atom(ref name, _) if name.as_str() == "pi" => {
|
||||||
|
interms.push(Number::Float(OrderedFloat(f64::consts::PI)))
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
return Err(self.error_form(
|
||||||
|
MachineError::instantiation_error(),
|
||||||
|
caller,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(interms.pop().unwrap())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate)
|
||||||
|
fn rdiv(&self, r1: Rc<Rational>, r2: Rc<Rational>) -> Result<Rational, MachineStub> {
|
||||||
|
if &*r2 == &0 {
|
||||||
|
let stub = MachineError::functor_stub(clause_name!("(rdiv)"), 2);
|
||||||
|
Err(self.error_form(MachineError::evaluation_error(EvalError::ZeroDivisor), stub))
|
||||||
|
} else {
|
||||||
|
Ok(Rational::from(&*r1 / &*r2))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate)
|
||||||
|
fn int_floor_div(&self, n1: Number, n2: Number) -> Result<Integer, MachineStub> {
|
||||||
|
match n1 / n2 {
|
||||||
|
Ok(result) => Ok(rnd_i(&result).to_owned()),
|
||||||
|
Err(e) => {
|
||||||
|
let stub = MachineError::functor_stub(clause_name!("(div)"), 2);
|
||||||
|
Err(self.error_form(
|
||||||
|
MachineError::evaluation_error(
|
||||||
|
e
|
||||||
|
),
|
||||||
|
stub
|
||||||
|
))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate)
|
||||||
|
fn idiv(&self, n1: Number, n2: Number) -> Result<Integer, MachineStub> {
|
||||||
|
match (n1, n2) {
|
||||||
|
(Number::Integer(n1), Number::Integer(n2)) => {
|
||||||
|
if &*n2 == &0 {
|
||||||
|
let stub = MachineError::functor_stub(clause_name!("(//)"), 2);
|
||||||
|
|
||||||
|
Err(self.error_form(
|
||||||
|
MachineError::evaluation_error(
|
||||||
|
EvalError::ZeroDivisor
|
||||||
|
),
|
||||||
|
stub,
|
||||||
|
))
|
||||||
|
} else {
|
||||||
|
Ok(<(Integer, Integer)>::from(n1.div_rem_ref(&*n2)).0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
(Number::Integer(_), n2) => {
|
||||||
|
let stub = MachineError::functor_stub(clause_name!("(//)"), 2);
|
||||||
|
|
||||||
|
Err(self.error_form(
|
||||||
|
MachineError::type_error(
|
||||||
|
self.heap.h(),
|
||||||
|
ValidType::Integer,
|
||||||
|
n2,
|
||||||
|
),
|
||||||
|
stub,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
(n1, _) => {
|
||||||
|
let stub = MachineError::functor_stub(clause_name!("(//)"), 2);
|
||||||
|
|
||||||
|
Err(self.error_form(
|
||||||
|
MachineError::type_error(
|
||||||
|
self.heap.h(),
|
||||||
|
ValidType::Integer,
|
||||||
|
n1,
|
||||||
|
),
|
||||||
|
stub,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate)
|
||||||
|
fn div(&self, n1: Number, n2: Number) -> Result<Number, MachineStub> {
|
||||||
|
let stub = MachineError::functor_stub(clause_name!("(/)"), 2);
|
||||||
|
|
||||||
|
if n2.is_zero() {
|
||||||
|
Err(self.error_form(MachineError::evaluation_error(EvalError::ZeroDivisor), stub))
|
||||||
|
} else {
|
||||||
|
try_numeric_result!(self, n1 / n2, stub)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate)
|
||||||
|
fn atan2(&self, n1: Number, n2: Number) -> Result<f64, MachineStub> {
|
||||||
|
let stub = MachineError::functor_stub(clause_name!("(is)"), 2);
|
||||||
|
|
||||||
|
if n1.is_zero() && n2.is_zero() {
|
||||||
|
Err(self.error_form(MachineError::evaluation_error(EvalError::Undefined), stub))
|
||||||
|
} else {
|
||||||
|
let f1 = self.float(n1)?;
|
||||||
|
let f2 = self.float(n2)?;
|
||||||
|
|
||||||
|
self.unary_float_fn_template(Number::Float(OrderedFloat(f1)), |f| f.atan2(f2))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate)
|
||||||
|
fn int_pow(&self, n1: Number, n2: Number) -> Result<Number, MachineStub> {
|
||||||
|
if n1.is_zero() && n2.is_negative() {
|
||||||
|
let stub = MachineError::functor_stub(clause_name!("(is)"), 2);
|
||||||
|
return Err(self.error_form(MachineError::evaluation_error(EvalError::Undefined), stub));
|
||||||
|
}
|
||||||
|
|
||||||
|
match (n1, n2) {
|
||||||
|
(Number::Integer(n1), Number::Integer(n2)) => {
|
||||||
|
if &*n1 != &1 && &*n2 < &0 {
|
||||||
|
let n = Number::Integer(n1);
|
||||||
|
let stub = MachineError::functor_stub(clause_name!("^"), 2);
|
||||||
|
|
||||||
|
Err(self.error_form(
|
||||||
|
MachineError::type_error(
|
||||||
|
self.heap.h(),
|
||||||
|
ValidType::Float,
|
||||||
|
n
|
||||||
|
),
|
||||||
|
stub,
|
||||||
|
))
|
||||||
|
} else {
|
||||||
|
Ok(Number::Integer(Rc::new(binary_pow(n1.as_ref().clone(), n2.as_ref()))))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
(n1, Number::Integer(n2)) => {
|
||||||
|
let f1 = self.float(n1)?;
|
||||||
|
let f2 = self.float(Number::Integer(n2))?;
|
||||||
|
|
||||||
|
self.unary_float_fn_template(Number::Float(OrderedFloat(f1)), |f| f.powf(f2))
|
||||||
|
.map(|f| Number::Float(OrderedFloat(f)))
|
||||||
|
}
|
||||||
|
(n1, n2) => {
|
||||||
|
let f2 = self.float(n2)?;
|
||||||
|
|
||||||
|
if n1.is_negative() && f2 != f2.floor() {
|
||||||
|
let stub = MachineError::functor_stub(clause_name!("(is)"), 2);
|
||||||
|
return Err(
|
||||||
|
self.error_form(MachineError::evaluation_error(EvalError::Undefined), stub)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
let f1 = self.float(n1)?;
|
||||||
|
self.unary_float_fn_template(Number::Float(OrderedFloat(f1)), |f| f.powf(f2))
|
||||||
|
.map(|f| Number::Float(OrderedFloat(f)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate)
|
||||||
|
fn gcd(&self, n1: Number, n2: Number) -> Result<Integer, MachineStub> {
|
||||||
|
match (n1, n2) {
|
||||||
|
(Number::Integer(n1), Number::Integer(n2)) => {
|
||||||
|
Ok(Integer::from(n1.gcd_ref(&n2)))
|
||||||
|
}
|
||||||
|
(Number::Float(f), _) | (_, Number::Float(f)) => {
|
||||||
|
let n = Number::Float(f);
|
||||||
|
let stub = MachineError::functor_stub(clause_name!("gcd"), 2);
|
||||||
|
|
||||||
|
Err(self.error_form(
|
||||||
|
MachineError::type_error(
|
||||||
|
self.heap.h(),
|
||||||
|
ValidType::Integer,
|
||||||
|
n
|
||||||
|
),
|
||||||
|
stub,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
(Number::Rational(r), _) | (_, Number::Rational(r)) => {
|
||||||
|
let n = Number::Rational(r);
|
||||||
|
let stub = MachineError::functor_stub(clause_name!("gcd"), 2);
|
||||||
|
|
||||||
|
Err(self.error_form(
|
||||||
|
MachineError::type_error(
|
||||||
|
self.heap.h(),
|
||||||
|
ValidType::Integer,
|
||||||
|
n,
|
||||||
|
),
|
||||||
|
stub,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate)
|
||||||
|
fn float_pow(&self, n1: Number, n2: Number) -> Result<Number, MachineStub> {
|
||||||
|
let f1 = result_f(&n1, rnd_f);
|
||||||
|
let f2 = result_f(&n2, rnd_f);
|
||||||
|
|
||||||
|
let stub = MachineError::functor_stub(clause_name!("(**)"), 2);
|
||||||
|
|
||||||
|
let f1 = try_numeric_result!(self, f1, stub)?;
|
||||||
|
let f2 = try_numeric_result!(self, f2, stub)?;
|
||||||
|
|
||||||
|
let result = result_f(&Number::Float(OrderedFloat(f1.powf(f2))), rnd_f);
|
||||||
|
|
||||||
|
Ok(Number::Float(OrderedFloat(try_numeric_result!(
|
||||||
|
self, result, stub
|
||||||
|
)?)))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate)
|
||||||
|
fn pow(&self, n1: Number, n2: Number, culprit: &'static str) -> Result<Number, MachineStub> {
|
||||||
|
if n2.is_negative() && n1.is_zero() {
|
||||||
|
let stub = MachineError::functor_stub(clause_name!(culprit), 2);
|
||||||
|
return Err(self.error_form(MachineError::evaluation_error(EvalError::Undefined), stub));
|
||||||
|
}
|
||||||
|
|
||||||
|
match (n1, n2) {
|
||||||
|
(Number::Integer(n1), Number::Integer(n2)) => {
|
||||||
|
Ok(Number::Integer(Rc::new(binary_pow(n1.as_ref().clone(), &*n2))))
|
||||||
|
}
|
||||||
|
(n1, n2) => {
|
||||||
|
self.float_pow(n1, n2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate)
|
||||||
|
fn unary_float_fn_template<FloatFn>(&self, n1: Number, f: FloatFn) -> Result<f64, MachineStub>
|
||||||
|
where
|
||||||
|
FloatFn: Fn(f64) -> f64,
|
||||||
|
{
|
||||||
|
let stub = MachineError::functor_stub(clause_name!("(is)"), 2);
|
||||||
|
|
||||||
|
let f1 = try_numeric_result!(self, result_f(&n1, rnd_f), stub)?;
|
||||||
|
let f1 = result_f(&Number::Float(OrderedFloat(f(f1))), rnd_f);
|
||||||
|
|
||||||
|
try_numeric_result!(self, f1, stub)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate)
|
||||||
|
fn sin(&self, n1: Number) -> Result<f64, MachineStub> {
|
||||||
|
self.unary_float_fn_template(n1, |f| f.sin())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate)
|
||||||
|
fn cos(&self, n1: Number) -> Result<f64, MachineStub> {
|
||||||
|
self.unary_float_fn_template(n1, |f| f.cos())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate)
|
||||||
|
fn tan(&self, n1: Number) -> Result<f64, MachineStub> {
|
||||||
|
self.unary_float_fn_template(n1, |f| f.tan())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate)
|
||||||
|
fn log(&self, n1: Number) -> Result<f64, MachineStub> {
|
||||||
|
self.unary_float_fn_template(n1, |f| f.log(f64::consts::E))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate)
|
||||||
|
fn exp(&self, n1: Number) -> Result<f64, MachineStub> {
|
||||||
|
self.unary_float_fn_template(n1, |f| f.exp())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate)
|
||||||
|
fn asin(&self, n1: Number) -> Result<f64, MachineStub> {
|
||||||
|
self.unary_float_fn_template(n1, |f| f.asin())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate)
|
||||||
|
fn acos(&self, n1: Number) -> Result<f64, MachineStub> {
|
||||||
|
self.unary_float_fn_template(n1, |f| f.acos())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate)
|
||||||
|
fn atan(&self, n1: Number) -> Result<f64, MachineStub> {
|
||||||
|
self.unary_float_fn_template(n1, |f| f.atan())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate)
|
||||||
|
fn sqrt(&self, n1: Number) -> Result<f64, MachineStub> {
|
||||||
|
if n1.is_negative() {
|
||||||
|
let stub = MachineError::functor_stub(clause_name!("(is)"), 2);
|
||||||
|
return Err(self.error_form(MachineError::evaluation_error(EvalError::Undefined), stub));
|
||||||
|
}
|
||||||
|
|
||||||
|
self.unary_float_fn_template(n1, |f| f.sqrt())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate)
|
||||||
|
fn float(&self, n: Number) -> Result<f64, MachineStub> {
|
||||||
|
let stub = MachineError::functor_stub(clause_name!("(is)"), 2);
|
||||||
|
try_numeric_result!(self, result_f(&n, rnd_f), stub)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate)
|
||||||
|
fn floor(&self, n1: Number) -> Integer {
|
||||||
|
rnd_i(&n1).to_owned()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate)
|
||||||
|
fn ceiling(&self, n1: Number) -> Integer {
|
||||||
|
-self.floor(-n1)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate)
|
||||||
|
fn truncate(&self, n: Number) -> Integer {
|
||||||
|
if n.is_negative() {
|
||||||
|
-self.floor(n.abs())
|
||||||
|
} else {
|
||||||
|
self.floor(n)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate)
|
||||||
|
fn round(&self, n: Number) -> Result<Integer, MachineStub> {
|
||||||
|
let stub = MachineError::functor_stub(clause_name!("(is)"), 2);
|
||||||
|
|
||||||
|
let result = n + Number::Float(OrderedFloat(0.5f64));
|
||||||
|
let result = try_numeric_result!(self, result, stub)?;
|
||||||
|
|
||||||
|
Ok(self.floor(result))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate)
|
||||||
|
fn shr(&self, n1: Number, n2: Number) -> Result<Integer, MachineStub> {
|
||||||
|
let stub = MachineError::functor_stub(clause_name!("(>>)"), 2);
|
||||||
|
|
||||||
|
match (n1, n2) {
|
||||||
|
(Number::Integer(n1), Number::Integer(n2)) =>
|
||||||
|
match n2.to_u32() {
|
||||||
|
Some(n2) => Ok(Integer::from(&*n1 >> n2)),
|
||||||
|
_ => Ok(Integer::from(&*n1 >> u32::max_value())),
|
||||||
|
},
|
||||||
|
(Number::Integer(_), n2) => Err(self.error_form(
|
||||||
|
MachineError::type_error(
|
||||||
|
self.heap.h(),
|
||||||
|
ValidType::Integer,
|
||||||
|
n2,
|
||||||
|
),
|
||||||
|
stub,
|
||||||
|
)),
|
||||||
|
(n1, _) => Err(self.error_form(
|
||||||
|
MachineError::type_error(
|
||||||
|
self.heap.h(),
|
||||||
|
ValidType::Integer,
|
||||||
|
n1,
|
||||||
|
),
|
||||||
|
stub,
|
||||||
|
)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate)
|
||||||
|
fn shl(&self, n1: Number, n2: Number) -> Result<Integer, MachineStub> {
|
||||||
|
let stub = MachineError::functor_stub(clause_name!("(<<)"), 2);
|
||||||
|
|
||||||
|
match (n1, n2) {
|
||||||
|
(Number::Integer(n1), Number::Integer(n2)) => match n2.to_u32() {
|
||||||
|
Some(n2) => Ok(Integer::from(&*n1 << n2)),
|
||||||
|
_ => Ok(Integer::from(&*n1 << u32::max_value())),
|
||||||
|
},
|
||||||
|
(Number::Integer(_), n2) => Err(self.error_form(
|
||||||
|
MachineError::type_error(
|
||||||
|
self.heap.h(),
|
||||||
|
ValidType::Integer,
|
||||||
|
n2,
|
||||||
|
),
|
||||||
|
stub,
|
||||||
|
)),
|
||||||
|
(n1, _) => Err(self.error_form(
|
||||||
|
MachineError::type_error(
|
||||||
|
self.heap.h(),
|
||||||
|
ValidType::Integer,
|
||||||
|
n1,
|
||||||
|
),
|
||||||
|
stub,
|
||||||
|
)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate)
|
||||||
|
fn bitwise_complement(&self, n1: Number) -> Result<Integer, MachineStub> {
|
||||||
|
let stub = MachineError::functor_stub(clause_name!("(\\)"), 2);
|
||||||
|
|
||||||
|
match n1 {
|
||||||
|
Number::Integer(n1) => Ok(Integer::from(!&*n1)),
|
||||||
|
_ => Err(self.error_form(
|
||||||
|
MachineError::type_error(
|
||||||
|
self.heap.h(),
|
||||||
|
ValidType::Integer,
|
||||||
|
n1,
|
||||||
|
),
|
||||||
|
stub,
|
||||||
|
)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate)
|
||||||
|
fn xor(&self, n1: Number, n2: Number) -> Result<Integer, MachineStub> {
|
||||||
|
let stub = MachineError::functor_stub(clause_name!("(xor)"), 2);
|
||||||
|
|
||||||
|
match (n1, n2) {
|
||||||
|
(Number::Integer(n1), Number::Integer(n2)) => {
|
||||||
|
Ok(Integer::from(&*n1 ^ &*n2))
|
||||||
|
}
|
||||||
|
(Number::Integer(_), n2) => {
|
||||||
|
Err(self.error_form(
|
||||||
|
MachineError::type_error(
|
||||||
|
self.heap.h(),
|
||||||
|
ValidType::Integer,
|
||||||
|
n2
|
||||||
|
),
|
||||||
|
stub,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
(n1, _) => {
|
||||||
|
Err(self.error_form(
|
||||||
|
MachineError::type_error(
|
||||||
|
self.heap.h(),
|
||||||
|
ValidType::Integer,
|
||||||
|
n1
|
||||||
|
),
|
||||||
|
stub,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate)
|
||||||
|
fn and(&self, n1: Number, n2: Number) -> Result<Integer, MachineStub> {
|
||||||
|
let stub = MachineError::functor_stub(clause_name!("(/\\)"), 2);
|
||||||
|
|
||||||
|
match (n1, n2) {
|
||||||
|
(Number::Integer(n1), Number::Integer(n2)) => Ok(Integer::from(&*n1 & &*n2)),
|
||||||
|
(Number::Integer(_), n2) => Err(self.error_form(
|
||||||
|
MachineError::type_error(
|
||||||
|
self.heap.h(),
|
||||||
|
ValidType::Integer,
|
||||||
|
n2,
|
||||||
|
),
|
||||||
|
stub,
|
||||||
|
)),
|
||||||
|
(n1, _) => Err(self.error_form(
|
||||||
|
MachineError::type_error(
|
||||||
|
self.heap.h(),
|
||||||
|
ValidType::Integer,
|
||||||
|
n1,
|
||||||
|
),
|
||||||
|
stub,
|
||||||
|
)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate)
|
||||||
|
fn modulus(&self, x: Number, y: Number) -> Result<Integer, MachineStub> {
|
||||||
|
let stub = MachineError::functor_stub(clause_name!("(mod)"), 2);
|
||||||
|
|
||||||
|
match (x, y) {
|
||||||
|
(Number::Integer(x), Number::Integer(y)) => {
|
||||||
|
if &*y == &0 {
|
||||||
|
Err(self.error_form(
|
||||||
|
MachineError::evaluation_error(EvalError::ZeroDivisor),
|
||||||
|
stub,
|
||||||
|
))
|
||||||
|
} else {
|
||||||
|
Ok(<(Integer, Integer)>::from(x.div_rem_floor_ref(&*y)).1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
(Number::Integer(_), n2) => Err(self.error_form(
|
||||||
|
MachineError::type_error(
|
||||||
|
self.heap.h(),
|
||||||
|
ValidType::Integer,
|
||||||
|
n2,
|
||||||
|
),
|
||||||
|
stub,
|
||||||
|
)),
|
||||||
|
(n1, _) => Err(self.error_form(
|
||||||
|
MachineError::type_error(
|
||||||
|
self.heap.h(),
|
||||||
|
ValidType::Integer,
|
||||||
|
n1,
|
||||||
|
),
|
||||||
|
stub,
|
||||||
|
)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate)
|
||||||
|
fn max(&self, n1: Number, n2: Number) -> Result<Number, MachineStub> {
|
||||||
|
match (n1, n2) {
|
||||||
|
(Number::Integer(n1), Number::Integer(n2)) => {
|
||||||
|
if n1 > n2 {
|
||||||
|
Ok(Number::Integer(n1))
|
||||||
|
} else {
|
||||||
|
Ok(Number::Integer(n2))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
(n1, n2) => {
|
||||||
|
let stub = MachineError::functor_stub(clause_name!("max"), 2);
|
||||||
|
|
||||||
|
let f1 = try_numeric_result!(self, result_f(&n1, rnd_f), stub)?;
|
||||||
|
let f2 = try_numeric_result!(self, result_f(&n2, rnd_f), stub)?;
|
||||||
|
|
||||||
|
Ok(Number::Float(cmp::max(OrderedFloat(f1), OrderedFloat(f2))))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate)
|
||||||
|
fn min(&self, n1: Number, n2: Number) -> Result<Number, MachineStub> {
|
||||||
|
match (n1, n2) {
|
||||||
|
(Number::Integer(n1), Number::Integer(n2)) => {
|
||||||
|
if n1 < n2 {
|
||||||
|
Ok(Number::Integer(n1))
|
||||||
|
} else {
|
||||||
|
Ok(Number::Integer(n2))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
(n1, n2) => {
|
||||||
|
let stub = MachineError::functor_stub(clause_name!("max"), 2);
|
||||||
|
|
||||||
|
let f1 = try_numeric_result!(self, result_f(&n1, rnd_f), stub)?;
|
||||||
|
let f2 = try_numeric_result!(self, result_f(&n2, rnd_f), stub)?;
|
||||||
|
|
||||||
|
Ok(Number::Float(cmp::min(OrderedFloat(f1), OrderedFloat(f2))))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate)
|
||||||
|
fn sign(&self, n: Number) -> Integer {
|
||||||
|
if n.is_positive() {
|
||||||
|
Integer::from(1)
|
||||||
|
} else if n.is_negative() {
|
||||||
|
Integer::from(-1)
|
||||||
|
} else {
|
||||||
|
Integer::from(0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate)
|
||||||
|
fn remainder(&self, n1: Number, n2: Number) -> Result<Integer, MachineStub> {
|
||||||
|
let stub = MachineError::functor_stub(clause_name!("(rem)"), 2);
|
||||||
|
|
||||||
|
match (n1, n2) {
|
||||||
|
(Number::Integer(n1), Number::Integer(n2)) => {
|
||||||
|
if &*n2 == &0 {
|
||||||
|
Err(self
|
||||||
|
.error_form(MachineError::evaluation_error(EvalError::ZeroDivisor), stub))
|
||||||
|
} else {
|
||||||
|
Ok(Integer::from(&*n1 % &*n2))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
(Number::Integer(_), n2) => Err(self.error_form(
|
||||||
|
MachineError::type_error(
|
||||||
|
self.heap.h(),
|
||||||
|
ValidType::Integer,
|
||||||
|
n2,
|
||||||
|
),
|
||||||
|
stub,
|
||||||
|
)),
|
||||||
|
(n1, _) => Err(self.error_form(
|
||||||
|
MachineError::type_error(
|
||||||
|
self.heap.h(),
|
||||||
|
ValidType::Integer,
|
||||||
|
n1,
|
||||||
|
),
|
||||||
|
stub,
|
||||||
|
)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate)
|
||||||
|
fn or(&self, n1: Number, n2: Number) -> Result<Integer, MachineStub> {
|
||||||
|
let stub = MachineError::functor_stub(clause_name!("(\\/)"), 2);
|
||||||
|
|
||||||
|
match (n1, n2) {
|
||||||
|
(Number::Integer(n1), Number::Integer(n2)) => {
|
||||||
|
Ok(Integer::from(&*n1 | &*n2))
|
||||||
|
}
|
||||||
|
(Number::Integer(_), n2) => {
|
||||||
|
Err(self.error_form(
|
||||||
|
MachineError::type_error(
|
||||||
|
self.heap.h(),
|
||||||
|
ValidType::Integer,
|
||||||
|
n2,
|
||||||
|
),
|
||||||
|
stub,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
(n1, _) => {
|
||||||
|
Err(self.error_form(
|
||||||
|
MachineError::type_error(
|
||||||
|
self.heap.h(),
|
||||||
|
ValidType::Integer,
|
||||||
|
n1
|
||||||
|
),
|
||||||
|
stub,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
use crate::prolog::machine::*;
|
use crate::prolog::machine::*;
|
||||||
|
|
||||||
|
use std::cmp::Ordering;
|
||||||
use std::vec::IntoIter;
|
use std::vec::IntoIter;
|
||||||
|
|
||||||
pub static VERIFY_ATTRS: &str = include_str!("attributed_variables.pl");
|
pub static VERIFY_ATTRS: &str = include_str!("attributed_variables.pl");
|
||||||
@@ -66,7 +67,7 @@ impl MachineState {
|
|||||||
.attr_var_init
|
.attr_var_init
|
||||||
.bindings
|
.bindings
|
||||||
.iter()
|
.iter()
|
||||||
.map(|(ref h, _)| Addr::AttrVar(*h));
|
.map(|(ref h, _)| HeapCellValue::Addr(Addr::AttrVar(*h)));
|
||||||
|
|
||||||
let var_list_addr = Addr::HeapCell(self.heap.to_list(iter));
|
let var_list_addr = Addr::HeapCell(self.heap.to_list(iter));
|
||||||
|
|
||||||
@@ -74,7 +75,7 @@ impl MachineState {
|
|||||||
.attr_var_init
|
.attr_var_init
|
||||||
.bindings
|
.bindings
|
||||||
.drain(0 ..)
|
.drain(0 ..)
|
||||||
.map(|(_, addr)| addr);
|
.map(|(_, addr)| HeapCellValue::Addr(addr));
|
||||||
|
|
||||||
let value_list_addr = Addr::HeapCell(self.heap.to_list(iter));
|
let value_list_addr = Addr::HeapCell(self.heap.to_list(iter));
|
||||||
(var_list_addr, value_list_addr)
|
(var_list_addr, value_list_addr)
|
||||||
@@ -100,7 +101,9 @@ impl MachineState {
|
|||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
attr_vars.sort_unstable_by(|a1, a2| self.compare_term_test(a1, a2));
|
attr_vars.sort_unstable_by(|a1, a2| {
|
||||||
|
self.compare_term_test(a1, a2).unwrap_or(Ordering::Less)
|
||||||
|
});
|
||||||
|
|
||||||
self.term_dedup(&mut attr_vars);
|
self.term_dedup(&mut attr_vars);
|
||||||
attr_vars.into_iter()
|
attr_vars.into_iter()
|
||||||
@@ -117,9 +120,9 @@ impl MachineState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
self.stack.index_and_frame_mut(e)[self.num_of_args + 1] =
|
self.stack.index_and_frame_mut(e)[self.num_of_args + 1] =
|
||||||
Addr::Con(Constant::CutPoint(self.b0));
|
Addr::CutPoint(self.b0);
|
||||||
self.stack.index_and_frame_mut(e)[self.num_of_args + 2] =
|
self.stack.index_and_frame_mut(e)[self.num_of_args + 2] =
|
||||||
Addr::Con(Constant::Usize(self.num_of_args));
|
Addr::Usize(self.num_of_args);
|
||||||
|
|
||||||
self.verify_attributes();
|
self.verify_attributes();
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
use crate::prolog::machine::machine_indices::*;
|
use crate::prolog::machine::machine_indices::*;
|
||||||
use crate::prolog::machine::stack::*;
|
use crate::prolog::machine::stack::*;
|
||||||
|
use crate::prolog::machine::streams::*;
|
||||||
|
|
||||||
|
use std::mem;
|
||||||
use std::ops::IndexMut;
|
use std::ops::IndexMut;
|
||||||
|
|
||||||
type Trail = Vec<(Ref, HeapCellValue)>;
|
type Trail = Vec<(Ref, HeapCellValue)>;
|
||||||
@@ -11,12 +13,13 @@ pub enum AttrVarPolicy {
|
|||||||
StripAttributes
|
StripAttributes
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) trait CopierTarget: IndexMut<usize, Output = HeapCellValue> {
|
pub(crate)
|
||||||
fn threshold(&self) -> usize;
|
trait CopierTarget: IndexMut<usize, Output = HeapCellValue> {
|
||||||
fn push(&mut self, val: HeapCellValue);
|
|
||||||
fn store(&self, val: Addr) -> Addr;
|
|
||||||
fn deref(&self, val: Addr) -> Addr;
|
fn deref(&self, val: Addr) -> Addr;
|
||||||
|
fn push(&mut self, val: HeapCellValue);
|
||||||
fn stack(&mut self) -> &mut Stack;
|
fn stack(&mut self) -> &mut Stack;
|
||||||
|
fn store(&self, val: Addr) -> Addr;
|
||||||
|
fn threshold(&self) -> usize;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate)
|
pub(crate)
|
||||||
@@ -75,15 +78,15 @@ impl<T: CopierTarget> CopyTermState<T> {
|
|||||||
*self.value_at_scan() = HeapCellValue::Addr(Addr::Lis(threshold));
|
*self.value_at_scan() = HeapCellValue::Addr(Addr::Lis(threshold));
|
||||||
|
|
||||||
let ra = self.target[addr].as_addr(threshold);
|
let ra = self.target[addr].as_addr(threshold);
|
||||||
let rd = self.target.store(self.target.deref(ra.clone()));
|
let rd = self.target.store(self.target.deref(ra));
|
||||||
|
|
||||||
self.target.push(HeapCellValue::Addr(ra.clone()));
|
self.target.push(HeapCellValue::Addr(ra));
|
||||||
|
|
||||||
let hcv = HeapCellValue::Addr(self.target[addr + 1].as_addr(addr + 1));
|
let hcv = HeapCellValue::Addr(self.target[addr + 1].as_addr(addr + 1));
|
||||||
|
|
||||||
self.target.push(hcv);
|
self.target.push(hcv);
|
||||||
|
|
||||||
match rd.clone() {
|
match rd {
|
||||||
Addr::AttrVar(h) | Addr::HeapCell(h)
|
Addr::AttrVar(h) | Addr::HeapCell(h)
|
||||||
if h >= self.old_h => {
|
if h >= self.old_h => {
|
||||||
self.target[threshold] = HeapCellValue::Addr(rd)
|
self.target[threshold] = HeapCellValue::Addr(rd)
|
||||||
@@ -129,18 +132,18 @@ impl<T: CopierTarget> CopyTermState<T> {
|
|||||||
|
|
||||||
fn copy_partial_string(&mut self, addr: usize, n: usize) {
|
fn copy_partial_string(&mut self, addr: usize, n: usize) {
|
||||||
let threshold = self.target.threshold();
|
let threshold = self.target.threshold();
|
||||||
|
let tail_addr = self.target[addr + 1].as_addr(addr + 1);
|
||||||
|
|
||||||
|
let trail_item = mem::replace(
|
||||||
|
&mut self.target[addr + 1],
|
||||||
|
HeapCellValue::Addr(Addr::PStrLocation(threshold, 0)),
|
||||||
|
);
|
||||||
|
|
||||||
self.trail.push((
|
self.trail.push((
|
||||||
Ref::HeapCell(addr + 1),
|
Ref::HeapCell(addr + 1),
|
||||||
self.target[addr + 1].clone(),
|
trail_item,
|
||||||
));
|
));
|
||||||
|
|
||||||
let tail_addr = self.target[addr + 1].as_addr(addr + 1);
|
|
||||||
|
|
||||||
self.target[addr + 1] = HeapCellValue::Addr(
|
|
||||||
Addr::PStrLocation(threshold, 0)
|
|
||||||
);
|
|
||||||
|
|
||||||
let pstr =
|
let pstr =
|
||||||
match &self.target[addr] {
|
match &self.target[addr] {
|
||||||
HeapCellValue::PartialString(ref pstr) => {
|
HeapCellValue::PartialString(ref pstr) => {
|
||||||
@@ -205,7 +208,7 @@ impl<T: CopierTarget> CopyTermState<T> {
|
|||||||
if let AttrVarPolicy::DeepCopy = self.attr_var_policy {
|
if let AttrVarPolicy::DeepCopy = self.attr_var_policy {
|
||||||
self.target.push(HeapCellValue::Addr(Addr::AttrVar(threshold)));
|
self.target.push(HeapCellValue::Addr(Addr::AttrVar(threshold)));
|
||||||
|
|
||||||
let list_val = self.target[h + 1].clone();
|
let list_val = self.target[h + 1].context_free_clone();
|
||||||
self.target.push(list_val);
|
self.target.push(list_val);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -214,9 +217,9 @@ impl<T: CopierTarget> CopyTermState<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn copy_var(&mut self, addr: Addr) {
|
fn copy_var(&mut self, addr: Addr) {
|
||||||
let rd = self.target.store(self.target.deref(addr.clone()));
|
let rd = self.target.store(self.target.deref(addr));
|
||||||
|
|
||||||
match rd.clone() {
|
match rd {
|
||||||
Addr::AttrVar(h) | Addr::HeapCell(h) if h >= self.old_h => {
|
Addr::AttrVar(h) | Addr::HeapCell(h) if h >= self.old_h => {
|
||||||
*self.value_at_scan() = HeapCellValue::Addr(rd);
|
*self.value_at_scan() = HeapCellValue::Addr(rd);
|
||||||
self.scan += 1;
|
self.scan += 1;
|
||||||
@@ -232,7 +235,7 @@ impl<T: CopierTarget> CopyTermState<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn copy_structure(&mut self, addr: usize) {
|
fn copy_structure(&mut self, addr: usize) {
|
||||||
match self.target[addr].clone() {
|
match self.target[addr].context_free_clone() {
|
||||||
HeapCellValue::NamedStr(arity, name, fixity) => {
|
HeapCellValue::NamedStr(arity, name, fixity) => {
|
||||||
let threshold = self.target.threshold();
|
let threshold = self.target.threshold();
|
||||||
|
|
||||||
@@ -247,7 +250,7 @@ impl<T: CopierTarget> CopyTermState<T> {
|
|||||||
self.target.push(HeapCellValue::NamedStr(arity, name, fixity));
|
self.target.push(HeapCellValue::NamedStr(arity, name, fixity));
|
||||||
|
|
||||||
for i in 0..arity {
|
for i in 0..arity {
|
||||||
let hcv = self.target[addr + 1 + i].clone();
|
let hcv = self.target[addr + 1 + i].context_free_clone();
|
||||||
self.target.push(hcv);
|
self.target.push(hcv);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -266,13 +269,18 @@ impl<T: CopierTarget> CopyTermState<T> {
|
|||||||
|
|
||||||
while self.scan < self.target.threshold() {
|
while self.scan < self.target.threshold() {
|
||||||
match self.value_at_scan() {
|
match self.value_at_scan() {
|
||||||
HeapCellValue::NamedStr(..) => {
|
&mut HeapCellValue::Addr(addr) => {
|
||||||
self.scan += 1;
|
match addr {
|
||||||
}
|
Addr::Con(h) => {
|
||||||
HeapCellValue::Addr(ref addr) => {
|
self.target.push(self.target[h].context_free_clone());
|
||||||
match addr.clone() {
|
self.scan += 1;
|
||||||
Addr::Lis(addr) => {
|
}
|
||||||
self.copy_list(addr);
|
Addr::Stream(_) => {
|
||||||
|
self.target.push(HeapCellValue::Stream(Stream::null_stream()));
|
||||||
|
self.scan += 1;
|
||||||
|
}
|
||||||
|
Addr::Lis(h) => {
|
||||||
|
self.copy_list(h);
|
||||||
}
|
}
|
||||||
addr @ Addr::AttrVar(_)
|
addr @ Addr::AttrVar(_)
|
||||||
| addr @ Addr::HeapCell(_)
|
| addr @ Addr::HeapCell(_)
|
||||||
@@ -285,12 +293,12 @@ impl<T: CopierTarget> CopyTermState<T> {
|
|||||||
Addr::PStrLocation(addr, n) => {
|
Addr::PStrLocation(addr, n) => {
|
||||||
self.copy_partial_string_from(addr, n);
|
self.copy_partial_string_from(addr, n);
|
||||||
}
|
}
|
||||||
Addr::Con(_) | Addr::DBRef(_) | Addr::Stream(_) => {
|
_ => {
|
||||||
self.scan += 1;
|
self.scan += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
HeapCellValue::PartialString(_) => {
|
_ => {
|
||||||
self.scan += 1;
|
self.scan += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,12 +41,22 @@ impl Machine {
|
|||||||
let arity = self.machine_st[arity].clone();
|
let arity = self.machine_st[arity].clone();
|
||||||
|
|
||||||
let name = match self.machine_st.store(self.machine_st.deref(name)) {
|
let name = match self.machine_st.store(self.machine_st.deref(name)) {
|
||||||
Addr::Con(Constant::Atom(name, _)) => name,
|
Addr::Con(h) =>
|
||||||
|
if let HeapCellValue::Atom(ref name, _) = &self.machine_st.heap[h] {
|
||||||
|
name.clone()
|
||||||
|
} else {
|
||||||
|
unreachable!()
|
||||||
|
},
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let arity = match self.machine_st.store(self.machine_st.deref(arity)) {
|
let arity = match self.machine_st.store(self.machine_st.deref(arity)) {
|
||||||
Addr::Con(Constant::Integer(arity)) => arity.to_usize().unwrap(),
|
Addr::Con(h) =>
|
||||||
|
if let HeapCellValue::Integer(ref arity) = &self.machine_st.heap[h] {
|
||||||
|
arity.to_usize().unwrap()
|
||||||
|
} else {
|
||||||
|
unreachable!()
|
||||||
|
},
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -91,7 +101,7 @@ impl Machine {
|
|||||||
let (name, arity) = self.get_predicate_key(name, arity);
|
let (name, arity) = self.get_predicate_key(name, arity);
|
||||||
|
|
||||||
self.make_undefined(name.clone(), arity);
|
self.make_undefined(name.clone(), arity);
|
||||||
|
|
||||||
self.indices.remove_code_index((name.clone(), arity));
|
self.indices.remove_code_index((name.clone(), arity));
|
||||||
self.indices.remove_clause_subsection(name.owning_module(), name, arity);
|
self.indices.remove_clause_subsection(name.owning_module(), name, arity);
|
||||||
}
|
}
|
||||||
@@ -101,16 +111,21 @@ impl Machine {
|
|||||||
let module_addr = self.machine_st[module].clone();
|
let module_addr = self.machine_st[module].clone();
|
||||||
|
|
||||||
let module_name = match self.machine_st.store(self.machine_st.deref(module_addr)) {
|
let module_name = match self.machine_st.store(self.machine_st.deref(module_addr)) {
|
||||||
Addr::Con(Constant::Atom(module, _)) => match self.indices.modules.get_mut(&module) {
|
Addr::Con(h) =>
|
||||||
Some(ref mut module) => {
|
if let HeapCellValue::Atom(ref module, _) = &self.machine_st.heap[h] {
|
||||||
module.code_dir.remove(&(name.clone(), arity));
|
match self.indices.modules.get_mut(module) {
|
||||||
module.module_decl.name.clone()
|
Some(ref mut module) => {
|
||||||
}
|
module.code_dir.remove(&(name.clone(), arity));
|
||||||
_ => {
|
module.module_decl.name.clone()
|
||||||
self.machine_st.fail = true;
|
}
|
||||||
return;
|
_ => {
|
||||||
}
|
self.machine_st.fail = true;
|
||||||
},
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
unreachable!()
|
||||||
|
},
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -162,21 +177,34 @@ impl Machine {
|
|||||||
place.push_to_queue(&mut addrs, added_clause);
|
place.push_to_queue(&mut addrs, added_clause);
|
||||||
self.print_new_dynamic_clause(addrs, name.clone(), arity)
|
self.print_new_dynamic_clause(addrs, name.clone(), arity)
|
||||||
}
|
}
|
||||||
Err(err) => return self.machine_st.throw_exception(err),
|
Err(err) => {
|
||||||
|
return self.machine_st.throw_exception(err);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
self.handle_eval_result_from_dynamic_compile(pred_str, name, arity, place.predicate_name());
|
self.handle_eval_result_from_dynamic_compile(
|
||||||
|
pred_str,
|
||||||
|
name,
|
||||||
|
arity,
|
||||||
|
place.predicate_name(),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_module_atom_tbl(&mut self, module_addr: Addr, name: &mut ClauseName) -> bool {
|
fn set_module_atom_tbl(&mut self, module_addr: Addr, name: &mut ClauseName) -> bool {
|
||||||
let atom_tbl = match self.machine_st.store(self.machine_st.deref(module_addr)) {
|
let atom_tbl = match self.machine_st.store(self.machine_st.deref(module_addr)) {
|
||||||
Addr::Con(Constant::Atom(module, _)) => match self.indices.modules.get(&module) {
|
Addr::Con(h) =>
|
||||||
Some(ref module) => module.atom_tbl.clone(),
|
if let HeapCellValue::Atom(ref module, _) = &self.machine_st.heap[h] {
|
||||||
None => {
|
match self.indices.modules.get(module) {
|
||||||
|
Some(ref module) => module.atom_tbl.clone(),
|
||||||
|
None => {
|
||||||
|
self.machine_st.fail = true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
self.machine_st.fail = true;
|
self.machine_st.fail = true;
|
||||||
return false;
|
return false;
|
||||||
}
|
},
|
||||||
},
|
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -204,7 +232,12 @@ impl Machine {
|
|||||||
fn retract_from_dynamic_predicate_in_module(&mut self) {
|
fn retract_from_dynamic_predicate_in_module(&mut self) {
|
||||||
let index = self.machine_st[temp_v!(3)].clone();
|
let index = self.machine_st[temp_v!(3)].clone();
|
||||||
let index = match self.machine_st.store(self.machine_st.deref(index)) {
|
let index = match self.machine_st.store(self.machine_st.deref(index)) {
|
||||||
Addr::Con(Constant::Integer(n)) => n.to_usize().unwrap(),
|
Addr::Con(h) =>
|
||||||
|
if let HeapCellValue::Integer(ref n) = &self.machine_st.heap[h] {
|
||||||
|
n.to_usize().unwrap()
|
||||||
|
} else {
|
||||||
|
unreachable!()
|
||||||
|
},
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -224,7 +257,9 @@ impl Machine {
|
|||||||
|
|
||||||
self.print_new_dynamic_clause(addrs, name.clone(), arity)
|
self.print_new_dynamic_clause(addrs, name.clone(), arity)
|
||||||
}
|
}
|
||||||
Err(err) => return self.machine_st.throw_exception(err),
|
Err(err) => {
|
||||||
|
return self.machine_st.throw_exception(err);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
self.handle_eval_result_from_dynamic_compile(
|
self.handle_eval_result_from_dynamic_compile(
|
||||||
@@ -239,8 +274,15 @@ impl Machine {
|
|||||||
fn retract_from_dynamic_predicate(&mut self) {
|
fn retract_from_dynamic_predicate(&mut self) {
|
||||||
let index = self.machine_st[temp_v!(3)].clone();
|
let index = self.machine_st[temp_v!(3)].clone();
|
||||||
let index = match self.machine_st.store(self.machine_st.deref(index)) {
|
let index = match self.machine_st.store(self.machine_st.deref(index)) {
|
||||||
Addr::Con(Constant::Integer(n)) => n.to_usize().unwrap(),
|
Addr::Con(h) =>
|
||||||
_ => unreachable!(),
|
if let HeapCellValue::Integer(n) = &self.machine_st.heap[h] {
|
||||||
|
n.to_usize().unwrap()
|
||||||
|
} else {
|
||||||
|
unreachable!()
|
||||||
|
},
|
||||||
|
_ => {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let (name, arity) = self.get_predicate_key(temp_v!(1), temp_v!(2));
|
let (name, arity) = self.get_predicate_key(temp_v!(1), temp_v!(2));
|
||||||
@@ -257,7 +299,9 @@ impl Machine {
|
|||||||
|
|
||||||
self.print_new_dynamic_clause(addrs, name.clone(), arity)
|
self.print_new_dynamic_clause(addrs, name.clone(), arity)
|
||||||
}
|
}
|
||||||
Err(err) => return self.machine_st.throw_exception(err),
|
Err(err) => {
|
||||||
|
return self.machine_st.throw_exception(err);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
self.handle_eval_result_from_dynamic_compile(
|
self.handle_eval_result_from_dynamic_compile(
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
use core::marker::PhantomData;
|
use core::marker::PhantomData;
|
||||||
|
|
||||||
use crate::prolog_parser::ast::*;
|
use crate::prolog_parser::ast::Constant;
|
||||||
|
|
||||||
use crate::prolog::machine::machine_indices::*;
|
use crate::prolog::machine::machine_indices::*;
|
||||||
use crate::prolog::machine::partial_string::*;
|
use crate::prolog::machine::partial_string::*;
|
||||||
@@ -140,17 +140,175 @@ impl<T: RawBlockTraits> HeapTemplate<T> {
|
|||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub(crate)
|
pub(crate)
|
||||||
fn push(&mut self, val: HeapCellValue) {
|
fn clone(&self, h: usize) -> HeapCellValue {
|
||||||
unsafe {
|
match &self[h] {
|
||||||
let new_top = self.buf.new_block(mem::size_of::<HeapCellValue>());
|
&HeapCellValue::Addr(addr) => {
|
||||||
ptr::write(self.buf.top as *mut _, val);
|
HeapCellValue::Addr(addr)
|
||||||
self.buf.top = new_top;
|
}
|
||||||
|
&HeapCellValue::Atom(ref name, ref op) => {
|
||||||
|
HeapCellValue::Atom(name.clone(), op.clone())
|
||||||
|
}
|
||||||
|
&HeapCellValue::DBRef(ref db_ref) => {
|
||||||
|
HeapCellValue::DBRef(db_ref.clone())
|
||||||
|
}
|
||||||
|
&HeapCellValue::Integer(ref n) => {
|
||||||
|
HeapCellValue::Integer(n.clone())
|
||||||
|
}
|
||||||
|
&HeapCellValue::NamedStr(arity, ref name, ref op) => {
|
||||||
|
HeapCellValue::NamedStr(arity, name.clone(), op.clone())
|
||||||
|
}
|
||||||
|
&HeapCellValue::Rational(ref r) => {
|
||||||
|
HeapCellValue::Rational(r.clone())
|
||||||
|
}
|
||||||
|
&HeapCellValue::PartialString(_) => {
|
||||||
|
HeapCellValue::Addr(Addr::PStrLocation(h, 0))
|
||||||
|
}
|
||||||
|
&HeapCellValue::Stream(_) => {
|
||||||
|
HeapCellValue::Addr(Addr::Stream(h))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub(crate)
|
pub(crate)
|
||||||
fn allocate_pstr(&mut self, mut src: &str) -> Option<Addr> {
|
fn put_constant(&mut self, c: Constant) -> Addr {
|
||||||
|
match c {
|
||||||
|
Constant::Atom(name, op) => {
|
||||||
|
Addr::Con(self.push(HeapCellValue::Atom(name, op)))
|
||||||
|
}
|
||||||
|
Constant::Char(c) => {
|
||||||
|
self.push(HeapCellValue::Addr(Addr::Char(c)));
|
||||||
|
Addr::Char(c)
|
||||||
|
}
|
||||||
|
Constant::CharCode(c) => {
|
||||||
|
self.push(HeapCellValue::Addr(Addr::CharCode(c)));
|
||||||
|
Addr::CharCode(c)
|
||||||
|
}
|
||||||
|
Constant::CutPoint(cp) => {
|
||||||
|
self.push(HeapCellValue::Addr(Addr::CutPoint(cp)));
|
||||||
|
Addr::CutPoint(cp)
|
||||||
|
}
|
||||||
|
Constant::EmptyList => {
|
||||||
|
self.push(HeapCellValue::Addr(Addr::EmptyList));
|
||||||
|
Addr::EmptyList
|
||||||
|
}
|
||||||
|
Constant::Integer(n) => {
|
||||||
|
Addr::Con(self.push(HeapCellValue::Integer(n)))
|
||||||
|
}
|
||||||
|
Constant::Rational(r) => {
|
||||||
|
Addr::Con(self.push(HeapCellValue::Rational(r)))
|
||||||
|
}
|
||||||
|
Constant::Float(f) => {
|
||||||
|
self.push(HeapCellValue::Addr(Addr::Float(f)));
|
||||||
|
Addr::Float(f)
|
||||||
|
}
|
||||||
|
Constant::String(s) => {
|
||||||
|
let addr = self.allocate_pstr(&s);
|
||||||
|
let h = self.h();
|
||||||
|
|
||||||
|
self[h - 1] = HeapCellValue::Addr(Addr::EmptyList);
|
||||||
|
addr
|
||||||
|
}
|
||||||
|
Constant::Usize(n) => {
|
||||||
|
self.push(HeapCellValue::Addr(Addr::Usize(n)));
|
||||||
|
Addr::Usize(n)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub(crate)
|
||||||
|
fn push(&mut self, val: HeapCellValue) -> usize {
|
||||||
|
let h = self.h();
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
let new_top = self.buf.new_block(mem::size_of::<HeapCellValue>());
|
||||||
|
ptr::write(self.buf.top as *mut _, val);
|
||||||
|
self.buf.top = new_top;
|
||||||
|
}
|
||||||
|
|
||||||
|
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 {
|
||||||
|
if let HeapCellValue::Atom(..) = &self[h] {
|
||||||
|
true
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub(crate)
|
||||||
|
fn to_unifiable(&mut self, non_heap_value: HeapCellValue) -> Addr {
|
||||||
|
match non_heap_value {
|
||||||
|
HeapCellValue::Addr(addr) => {
|
||||||
|
addr
|
||||||
|
}
|
||||||
|
val @ HeapCellValue::Atom(..)
|
||||||
|
| val @ HeapCellValue::Integer(_)
|
||||||
|
| val @ HeapCellValue::DBRef(_)
|
||||||
|
| val @ HeapCellValue::Rational(_) => {
|
||||||
|
Addr::Con(self.push(val))
|
||||||
|
}
|
||||||
|
val @ HeapCellValue::NamedStr(..) => {
|
||||||
|
Addr::Str(self.push(val))
|
||||||
|
}
|
||||||
|
val @ HeapCellValue::Stream(..) => {
|
||||||
|
Addr::Stream(self.push(val))
|
||||||
|
}
|
||||||
|
val @ HeapCellValue::PartialString(_) => {
|
||||||
|
let h = self.push(val);
|
||||||
|
self.push(HeapCellValue::Addr(Addr::EmptyList));
|
||||||
|
|
||||||
|
Addr::Con(h)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub(crate)
|
||||||
|
fn allocate_pstr(&mut self, src: &str) -> Addr {
|
||||||
|
self.write_pstr(src)
|
||||||
|
.unwrap_or_else(|| {
|
||||||
|
let h = self.h();
|
||||||
|
|
||||||
|
self.push(HeapCellValue::PartialString(
|
||||||
|
PartialString::empty()
|
||||||
|
));
|
||||||
|
|
||||||
|
self.push(HeapCellValue::Addr(
|
||||||
|
Addr::HeapCell(h + 1)
|
||||||
|
));
|
||||||
|
|
||||||
|
Addr::PStrLocation(h, 0)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn write_pstr(&mut self, mut src: &str) -> Option<Addr> {
|
||||||
let orig_h = self.h();
|
let orig_h = self.h();
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
@@ -245,17 +403,21 @@ impl<T: RawBlockTraits> HeapTemplate<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub(crate)
|
pub(crate)
|
||||||
fn to_list<Iter: Iterator<Item = Addr>>(&mut self, values: Iter) -> usize {
|
fn to_list<Iter, SrcT>(&mut self, values: Iter) -> usize
|
||||||
|
where Iter: Iterator<Item = SrcT>,
|
||||||
|
SrcT: Into<HeapCellValue>
|
||||||
|
{
|
||||||
let head_addr = self.h();
|
let head_addr = self.h();
|
||||||
|
let mut h = head_addr;
|
||||||
|
|
||||||
for value in values {
|
for value in values.map(|v| v.into()) {
|
||||||
let h = self.h();
|
|
||||||
|
|
||||||
self.push(HeapCellValue::Addr(Addr::Lis(h + 1)));
|
self.push(HeapCellValue::Addr(Addr::Lis(h + 1)));
|
||||||
self.push(HeapCellValue::Addr(value));
|
self.push(value);
|
||||||
|
|
||||||
|
h += mem::size_of::<HeapCellValue>() * 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
self.push(HeapCellValue::Addr(Addr::Con(Constant::EmptyList)));
|
self.push(HeapCellValue::Addr(Addr::EmptyList));
|
||||||
|
|
||||||
head_addr
|
head_addr
|
||||||
}
|
}
|
||||||
@@ -286,8 +448,8 @@ impl<T: RawBlockTraits> HeapTemplate<T> {
|
|||||||
pub(crate)
|
pub(crate)
|
||||||
fn to_local_code_ptr(&self, addr: &Addr) -> Option<LocalCodePtr> {
|
fn to_local_code_ptr(&self, addr: &Addr) -> Option<LocalCodePtr> {
|
||||||
let extract_integer = |s: usize| -> Option<usize> {
|
let extract_integer = |s: usize| -> Option<usize> {
|
||||||
match self[s].as_addr(s) {
|
match &self[s] {
|
||||||
Addr::Con(Constant::Integer(n)) => n.to_usize(),
|
&HeapCellValue::Integer(ref n) => n.to_usize(),
|
||||||
_ => None
|
_ => None
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -327,6 +489,19 @@ impl<T: RawBlockTraits> HeapTemplate<T> {
|
|||||||
_ => None
|
_ => None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub
|
||||||
|
fn index_addr<'a>(&'a self, addr: &Addr) -> RefOrOwned<'a, HeapCellValue> {
|
||||||
|
match addr {
|
||||||
|
&Addr::Con(h) | &Addr::Str(h) | &Addr::Stream(h) => {
|
||||||
|
RefOrOwned::Borrowed(&self[h])
|
||||||
|
}
|
||||||
|
addr => {
|
||||||
|
RefOrOwned::Owned(HeapCellValue::Addr(*addr))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: RawBlockTraits> Index<usize> for HeapTemplate<T> {
|
impl<T: RawBlockTraits> Index<usize> for HeapTemplate<T> {
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
use prolog_parser::ast::*;
|
use prolog_parser::ast::*;
|
||||||
|
|
||||||
use crate::prolog::forms::PredicateKey;
|
use crate::prolog::forms::{Number, PredicateKey};
|
||||||
|
use crate::prolog::machine::heap::*;
|
||||||
use crate::prolog::machine::machine_indices::*;
|
use crate::prolog::machine::machine_indices::*;
|
||||||
use crate::prolog::machine::machine_state::*;
|
use crate::prolog::machine::machine_state::*;
|
||||||
use crate::prolog::rug::Integer;
|
use crate::prolog::rug::Integer;
|
||||||
@@ -21,19 +22,140 @@ pub(super) struct MachineError {
|
|||||||
from: ErrorProvenance,
|
from: ErrorProvenance,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(super)
|
||||||
|
trait TypeError {
|
||||||
|
fn type_error(self, h: usize, valid_type: ValidType) -> MachineError;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TypeError for Addr {
|
||||||
|
fn type_error(self, _: usize, valid_type: ValidType) -> MachineError {
|
||||||
|
let stub = functor!(
|
||||||
|
"type_error",
|
||||||
|
[atom(valid_type.as_str()), addr(self)]
|
||||||
|
);
|
||||||
|
|
||||||
|
MachineError {
|
||||||
|
stub,
|
||||||
|
location: None,
|
||||||
|
from: ErrorProvenance::Received
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TypeError for MachineStub {
|
||||||
|
fn type_error(self, h: usize, valid_type: ValidType) -> MachineError {
|
||||||
|
let stub = functor!(
|
||||||
|
"type_error",
|
||||||
|
[atom(valid_type.as_str()), aux(h, 0)],
|
||||||
|
[self]
|
||||||
|
);
|
||||||
|
|
||||||
|
MachineError {
|
||||||
|
stub,
|
||||||
|
location: None,
|
||||||
|
from: ErrorProvenance::Constructed
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TypeError for Number {
|
||||||
|
fn type_error(self, _h: usize, valid_type: ValidType) -> MachineError {
|
||||||
|
let stub = functor!(
|
||||||
|
"type_error",
|
||||||
|
[atom(valid_type.as_str()), number(self)]
|
||||||
|
);
|
||||||
|
|
||||||
|
MachineError {
|
||||||
|
stub,
|
||||||
|
location: None,
|
||||||
|
from: ErrorProvenance::Received
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(super)
|
||||||
|
trait PermissionError {
|
||||||
|
fn permission_error(self, h: usize, index_str: &'static str, perm: Permission) -> MachineError;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PermissionError for Addr {
|
||||||
|
fn permission_error(self, _: usize, index_str: &'static str, perm: Permission) -> MachineError {
|
||||||
|
let stub = functor!(
|
||||||
|
"permission_error",
|
||||||
|
[atom(perm.as_str()), atom(index_str), addr(self)]
|
||||||
|
);
|
||||||
|
|
||||||
|
MachineError {
|
||||||
|
stub,
|
||||||
|
location: None,
|
||||||
|
from: ErrorProvenance::Received
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PermissionError for MachineStub {
|
||||||
|
fn permission_error(self, h: usize, index_str: &'static str, perm: Permission) -> MachineError {
|
||||||
|
let stub = functor!(
|
||||||
|
"permission_error",
|
||||||
|
[atom(perm.as_str()), atom(index_str), aux(h, 0)],
|
||||||
|
[self]
|
||||||
|
);
|
||||||
|
|
||||||
|
MachineError {
|
||||||
|
stub,
|
||||||
|
location: None,
|
||||||
|
from: ErrorProvenance::Constructed
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(super)
|
||||||
|
trait DomainError {
|
||||||
|
fn domain_error(self, error: DomainErrorType) -> MachineError;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DomainError for Addr {
|
||||||
|
fn domain_error(self, error: DomainErrorType) -> MachineError {
|
||||||
|
let stub = functor!(
|
||||||
|
"domain_error",
|
||||||
|
[atom(error.as_str()), addr(self)]
|
||||||
|
);
|
||||||
|
|
||||||
|
MachineError {
|
||||||
|
stub,
|
||||||
|
location: None,
|
||||||
|
from: ErrorProvenance::Received,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DomainError for Number {
|
||||||
|
fn domain_error(self, error: DomainErrorType) -> MachineError {
|
||||||
|
let stub = functor!(
|
||||||
|
"domain_error",
|
||||||
|
[atom(error.as_str()), number(self)]
|
||||||
|
);
|
||||||
|
|
||||||
|
MachineError {
|
||||||
|
stub,
|
||||||
|
location: None,
|
||||||
|
from: ErrorProvenance::Received,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl MachineError {
|
impl MachineError {
|
||||||
pub(super) fn functor_stub(name: ClauseName, arity: usize) -> MachineStub {
|
pub(super) fn functor_stub(name: ClauseName, arity: usize) -> MachineStub {
|
||||||
let name = HeapCellValue::Addr(Addr::Con(Constant::Atom(name, None)));
|
|
||||||
functor!(
|
functor!(
|
||||||
"/",
|
"/",
|
||||||
2,
|
SharedOpDesc::new(400, YFX),
|
||||||
[name, heap_integer!(Integer::from(arity))],
|
[clause_name(name), integer(arity)]
|
||||||
SharedOpDesc::new(400, YFX)
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn evaluation_error(eval_error: EvalError) -> Self {
|
pub(super) fn evaluation_error(eval_error: EvalError) -> Self {
|
||||||
let stub = functor!("evaluation_error", 1, [heap_atom!(eval_error.as_str())]);
|
let stub = functor!("evaluation_error", [atom(eval_error.as_str())]);
|
||||||
|
|
||||||
MachineError {
|
MachineError {
|
||||||
stub,
|
stub,
|
||||||
location: None,
|
location: None,
|
||||||
@@ -42,21 +164,8 @@ impl MachineError {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub(super)
|
pub(super)
|
||||||
fn type_error(valid_type: ValidType, culprit: Addr) -> Self {
|
fn type_error<T: TypeError>(h: usize, valid_type: ValidType, culprit: T) -> Self {
|
||||||
let stub = functor!(
|
culprit.type_error(h, valid_type)
|
||||||
"type_error",
|
|
||||||
2,
|
|
||||||
[
|
|
||||||
heap_atom!(valid_type.as_str()),
|
|
||||||
HeapCellValue::Addr(culprit)
|
|
||||||
]
|
|
||||||
);
|
|
||||||
|
|
||||||
MachineError {
|
|
||||||
stub,
|
|
||||||
location: None,
|
|
||||||
from: ErrorProvenance::Received,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super)
|
pub(super)
|
||||||
@@ -66,31 +175,24 @@ impl MachineError {
|
|||||||
name: ClauseName,
|
name: ClauseName,
|
||||||
arity: usize,
|
arity: usize,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let mod_name = HeapCellValue::Addr(Addr::Con(Constant::Atom(mod_name, None)));
|
let res_stub = functor!(
|
||||||
let name = HeapCellValue::Addr(Addr::Con(Constant::Atom(name, None)));
|
":",
|
||||||
|
SharedOpDesc::new(600, XFY),
|
||||||
let mut stub = functor!(
|
[clause_name(mod_name), clause_name(name)]
|
||||||
"evaluation_error",
|
|
||||||
1,
|
|
||||||
[HeapCellValue::Addr(Addr::HeapCell(h + 2))]
|
|
||||||
);
|
);
|
||||||
|
|
||||||
stub.append(&mut functor!(
|
let ind_stub = functor!(
|
||||||
"/",
|
"/",
|
||||||
2,
|
SharedOpDesc::new(400, YFX),
|
||||||
[
|
[aux(h + 2, 0), integer(arity)],
|
||||||
HeapCellValue::Addr(Addr::HeapCell(h + 2 + 3)),
|
[res_stub]
|
||||||
heap_integer!(Integer::from(arity))
|
);
|
||||||
],
|
|
||||||
SharedOpDesc::new(400, YFX)
|
let stub = functor!(
|
||||||
));
|
"evaluation_error",
|
||||||
|
[aux(h, 0)],
|
||||||
stub.append(&mut functor!(
|
[ind_stub]
|
||||||
":",
|
);
|
||||||
2,
|
|
||||||
[mod_name, name],
|
|
||||||
SharedOpDesc::new(600, XFY)
|
|
||||||
));
|
|
||||||
|
|
||||||
MachineError {
|
MachineError {
|
||||||
stub,
|
stub,
|
||||||
@@ -103,23 +205,29 @@ impl MachineError {
|
|||||||
fn existence_error(h: usize, err: ExistenceError) -> Self {
|
fn existence_error(h: usize, err: ExistenceError) -> Self {
|
||||||
match err {
|
match err {
|
||||||
ExistenceError::Module(name) => {
|
ExistenceError::Module(name) => {
|
||||||
let name = HeapCellValue::Addr(Addr::Con(Constant::Atom(name, None)));
|
let stub = functor!(
|
||||||
let stub = functor!("existence_error", 2, [heap_atom!("module"), name]);
|
"existence_error",
|
||||||
|
[atom("module"), clause_name(name)]
|
||||||
|
);
|
||||||
|
|
||||||
MachineError {
|
MachineError {
|
||||||
stub,
|
stub,
|
||||||
location: None,
|
location: None,
|
||||||
from: ErrorProvenance::Constructed,
|
from: ErrorProvenance::Received,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ExistenceError::Procedure(name, arity) => {
|
ExistenceError::Procedure(name, arity) => {
|
||||||
let mut stub = functor!(
|
let culprit = functor!(
|
||||||
"existence_error",
|
"/",
|
||||||
2,
|
SharedOpDesc::new(400, YFX),
|
||||||
[heap_atom!("procedure"), heap_str!(3 + h)]
|
[clause_name(name), integer(arity)]
|
||||||
);
|
);
|
||||||
|
|
||||||
stub.append(&mut Self::functor_stub(name, arity));
|
let stub = functor!(
|
||||||
|
"existence_error",
|
||||||
|
[atom("procedure"), aux(h, 0)],
|
||||||
|
[culprit]
|
||||||
|
);
|
||||||
|
|
||||||
MachineError {
|
MachineError {
|
||||||
stub,
|
stub,
|
||||||
@@ -127,99 +235,115 @@ impl MachineError {
|
|||||||
from: ErrorProvenance::Constructed,
|
from: ErrorProvenance::Constructed,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ExistenceError::Stream(addr) => {
|
ExistenceError::Stream(culprit) => {
|
||||||
let culprit = HeapCellValue::Addr(addr);
|
let stub = functor!(
|
||||||
let stub = functor!("existence_error", 2, [heap_atom!("stream"), culprit]);
|
"existence_error",
|
||||||
|
[atom("stream"), addr(culprit)]
|
||||||
|
);
|
||||||
|
|
||||||
MachineError {
|
MachineError {
|
||||||
stub,
|
stub,
|
||||||
location: None,
|
location: None,
|
||||||
from: ErrorProvenance::Constructed,
|
from: ErrorProvenance::Received,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(super)
|
||||||
|
fn permission_error<T: PermissionError>(
|
||||||
|
h: usize,
|
||||||
|
err: Permission,
|
||||||
|
index_str: &'static str,
|
||||||
|
culprit: T,
|
||||||
|
) -> Self {
|
||||||
|
culprit.permission_error(
|
||||||
|
h,
|
||||||
|
index_str,
|
||||||
|
err,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn arithmetic_error(h: usize, err: ArithmeticError) -> Self {
|
||||||
|
match err {
|
||||||
|
ArithmeticError::UninstantiatedVar => {
|
||||||
|
Self::instantiation_error()
|
||||||
|
}
|
||||||
|
ArithmeticError::NonEvaluableFunctor(name, arity) => {
|
||||||
|
let culprit = functor!(
|
||||||
|
"/",
|
||||||
|
SharedOpDesc::new(400, YFX),
|
||||||
|
[constant(h, &name), integer(arity)]
|
||||||
|
);
|
||||||
|
|
||||||
|
Self::type_error(h, ValidType::Evaluable, culprit)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub(super)
|
||||||
|
fn domain_error<T: DomainError>(error: DomainErrorType, culprit: T) -> Self {
|
||||||
|
culprit.domain_error(error)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(super)
|
||||||
|
fn instantiation_error() -> Self {
|
||||||
|
let stub = functor!("instantiation_error");
|
||||||
|
|
||||||
|
MachineError {
|
||||||
|
stub,
|
||||||
|
location: None,
|
||||||
|
from: ErrorProvenance::Received,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub(super)
|
pub(super)
|
||||||
fn session_error(h: usize, err: SessionError) -> Self {
|
fn session_error(h: usize, err: SessionError) -> Self {
|
||||||
match err {
|
match err {
|
||||||
SessionError::ParserError(err) => Self::syntax_error(h, err),
|
SessionError::ParserError(err) => {
|
||||||
|
Self::syntax_error(h, err)
|
||||||
|
}
|
||||||
SessionError::CannotOverwriteBuiltIn(pred_str)
|
SessionError::CannotOverwriteBuiltIn(pred_str)
|
||||||
| SessionError::CannotOverwriteImport(pred_str) => {
|
| SessionError::CannotOverwriteImport(pred_str) => {
|
||||||
Self::permission_error(
|
Self::permission_error(
|
||||||
PermissionError::Modify,
|
h,
|
||||||
"private_procedure",
|
Permission::Modify,
|
||||||
Addr::Con(Constant::Atom(pred_str, None)),
|
"private_procedure",
|
||||||
|
functor!(clause_name(pred_str)),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
SessionError::InvalidFileName(filename) => {
|
SessionError::InvalidFileName(filename) => {
|
||||||
Self::existence_error(h, ExistenceError::Module(filename))
|
Self::existence_error(h, ExistenceError::Module(filename))
|
||||||
}
|
}
|
||||||
SessionError::ModuleDoesNotContainExport(..) => Self::permission_error(
|
SessionError::ModuleDoesNotContainExport(..) => {
|
||||||
PermissionError::Access,
|
Self::permission_error(
|
||||||
"private_procedure",
|
h,
|
||||||
Addr::Con(atom!("module_does_not_contain_claimed_export")),
|
Permission::Access,
|
||||||
),
|
"private_procedure",
|
||||||
SessionError::ModuleNotFound => Self::permission_error(
|
functor!("module_does_not_contain_claimed_export"),
|
||||||
PermissionError::Access,
|
)
|
||||||
"private_procedure",
|
}
|
||||||
Addr::Con(atom!("module_does_not_exist")),
|
SessionError::ModuleNotFound => {
|
||||||
),
|
Self::permission_error(
|
||||||
|
h,
|
||||||
|
Permission::Access,
|
||||||
|
"private_procedure",
|
||||||
|
functor!("modules_does_not_exist"),
|
||||||
|
)
|
||||||
|
}
|
||||||
SessionError::OpIsInfixAndPostFix(op) => {
|
SessionError::OpIsInfixAndPostFix(op) => {
|
||||||
Self::permission_error(
|
Self::permission_error(
|
||||||
PermissionError::Create,
|
h,
|
||||||
|
Permission::Create,
|
||||||
"operator",
|
"operator",
|
||||||
Addr::Con(Constant::Atom(op, None)),
|
functor!(clause_name(op)),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super)
|
|
||||||
fn permission_error(
|
|
||||||
err: PermissionError,
|
|
||||||
index_str: &'static str,
|
|
||||||
culprit: Addr,
|
|
||||||
) -> Self {
|
|
||||||
let culprit = HeapCellValue::Addr(culprit);
|
|
||||||
|
|
||||||
let err = vec![heap_atom!(err.as_str()), heap_atom!(index_str), culprit];
|
|
||||||
let mut stub = functor!("permission_error", 3);
|
|
||||||
|
|
||||||
stub.extend(err.into_iter());
|
|
||||||
|
|
||||||
MachineError {
|
|
||||||
stub,
|
|
||||||
location: None,
|
|
||||||
from: ErrorProvenance::Constructed,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn arithmetic_error(h: usize, err: ArithmeticError) -> Self {
|
|
||||||
match err {
|
|
||||||
ArithmeticError::UninstantiatedVar => Self::instantiation_error(),
|
|
||||||
ArithmeticError::NonEvaluableFunctor(name, arity) => {
|
|
||||||
let name = HeapCellValue::Addr(Addr::Con(name));
|
|
||||||
let culprit = functor!(
|
|
||||||
"/",
|
|
||||||
2,
|
|
||||||
[name, heap_integer!(Integer::from(arity))],
|
|
||||||
SharedOpDesc::new(400, YFX)
|
|
||||||
);
|
|
||||||
|
|
||||||
let mut stub = Self::type_error(ValidType::Evaluable, Addr::HeapCell(3 + h)).stub;
|
|
||||||
stub.extend(culprit.into_iter());
|
|
||||||
|
|
||||||
MachineError {
|
|
||||||
stub,
|
|
||||||
location: None,
|
|
||||||
from: ErrorProvenance::Constructed,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(super)
|
pub(super)
|
||||||
fn syntax_error(h: usize, err: ParserError) -> Self {
|
fn syntax_error(h: usize, err: ParserError) -> Self {
|
||||||
if let ParserError::Arithmetic(err) = err {
|
if let ParserError::Arithmetic(err) = err {
|
||||||
@@ -227,15 +351,13 @@ impl MachineError {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let location = err.line_and_col_num();
|
let location = err.line_and_col_num();
|
||||||
let err = vec![heap_atom!(err.as_str())];
|
let stub = functor!(err.as_str());
|
||||||
|
|
||||||
let mut stub = if err.len() == 1 {
|
let stub = functor!(
|
||||||
functor!("syntax_error", 1)
|
"syntax_error",
|
||||||
} else {
|
[aux(h, 0)],
|
||||||
functor!("syntax_error", 1, [heap_str!(h + 2)])
|
[stub]
|
||||||
};
|
);
|
||||||
|
|
||||||
stub.extend(err.into_iter());
|
|
||||||
|
|
||||||
MachineError {
|
MachineError {
|
||||||
stub,
|
stub,
|
||||||
@@ -244,33 +366,10 @@ impl MachineError {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super)
|
|
||||||
fn domain_error(error: DomainError, culprit: Addr) -> Self {
|
|
||||||
let stub = functor!(
|
|
||||||
"domain_error",
|
|
||||||
2,
|
|
||||||
[heap_atom!(error.as_str()), HeapCellValue::Addr(culprit)]
|
|
||||||
);
|
|
||||||
MachineError {
|
|
||||||
stub,
|
|
||||||
location: None,
|
|
||||||
from: ErrorProvenance::Received,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(super)
|
|
||||||
fn instantiation_error() -> Self {
|
|
||||||
let stub = functor!("instantiation_error");
|
|
||||||
MachineError {
|
|
||||||
stub,
|
|
||||||
location: None,
|
|
||||||
from: ErrorProvenance::Received,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(super)
|
pub(super)
|
||||||
fn representation_error(flag: RepFlag) -> Self {
|
fn representation_error(flag: RepFlag) -> Self {
|
||||||
let stub = functor!("representation_error", 1, [heap_atom!(flag.as_str())]);
|
let stub = functor!("representation_error", [atom(flag.as_str())]);
|
||||||
|
|
||||||
MachineError {
|
MachineError {
|
||||||
stub,
|
stub,
|
||||||
location: None,
|
location: None,
|
||||||
@@ -296,7 +395,7 @@ impl MachineError {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy)]
|
||||||
pub enum PermissionError {
|
pub enum Permission {
|
||||||
Access,
|
Access,
|
||||||
Create,
|
Create,
|
||||||
InputStream,
|
InputStream,
|
||||||
@@ -304,14 +403,14 @@ pub enum PermissionError {
|
|||||||
OutputStream,
|
OutputStream,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PermissionError {
|
impl Permission {
|
||||||
pub fn as_str(self) -> &'static str {
|
pub fn as_str(self) -> &'static str {
|
||||||
match self {
|
match self {
|
||||||
PermissionError::Access => "access",
|
Permission::Access => "access",
|
||||||
PermissionError::Create => "create",
|
Permission::Create => "create",
|
||||||
PermissionError::InputStream => "input",
|
Permission::InputStream => "input",
|
||||||
PermissionError::Modify => "modify",
|
Permission::Modify => "modify",
|
||||||
PermissionError::OutputStream => "output",
|
Permission::OutputStream => "output",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -363,18 +462,18 @@ impl ValidType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy)]
|
||||||
pub enum DomainError {
|
pub enum DomainErrorType {
|
||||||
NotLessThanZero,
|
NotLessThanZero,
|
||||||
Stream,
|
Stream,
|
||||||
StreamOrAlias,
|
StreamOrAlias,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DomainError {
|
impl DomainErrorType {
|
||||||
pub fn as_str(self) -> &'static str {
|
pub fn as_str(self) -> &'static str {
|
||||||
match self {
|
match self {
|
||||||
DomainError::NotLessThanZero => "not_less_than_zero",
|
DomainErrorType::NotLessThanZero => "not_less_than_zero",
|
||||||
DomainError::Stream => "stream",
|
DomainErrorType::Stream => "stream",
|
||||||
DomainError::StreamOrAlias => "stream_or_alias",
|
DomainErrorType::StreamOrAlias => "stream_or_alias",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -424,20 +523,20 @@ impl EvalError {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// used by '$skip_max_list'.
|
// used by '$skip_max_list'.
|
||||||
|
#[derive(Clone, Copy)]
|
||||||
pub(super) enum CycleSearchResult {
|
pub(super) enum CycleSearchResult {
|
||||||
EmptyList,
|
EmptyList,
|
||||||
NotList,
|
NotList,
|
||||||
PartialList(usize, Ref), // the list length (up to max), and an offset into the heap.
|
PartialList(usize, Ref), // the list length (up to max), and an offset into the heap.
|
||||||
ProperList(usize), // the list length.
|
ProperList(usize), // the list length.
|
||||||
CompleteString(usize, Rc<String>), // the string length (in bytes), the string.
|
|
||||||
UntouchedString(usize, Rc<String>), // the cut off, past which is the untouched string.
|
|
||||||
PStrLocation(usize, usize, usize), // the list length (up to max), the heap offset, byte offset into the string.
|
PStrLocation(usize, usize, usize), // the list length (up to max), the heap offset, byte offset into the string.
|
||||||
UntouchedList(usize), // the address of an uniterated Addr::Lis(address).
|
UntouchedList(usize), // the address of an uniterated Addr::Lis(address).
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MachineState {
|
impl MachineState {
|
||||||
// see 8.4.3 of Draft Technical Corrigendum 2.
|
// see 8.4.3 of Draft Technical Corrigendum 2.
|
||||||
pub(super) fn check_sort_errors(&self) -> CallResult {
|
pub(super)
|
||||||
|
fn check_sort_errors(&self) -> CallResult {
|
||||||
let stub = MachineError::functor_stub(clause_name!("sort"), 2);
|
let stub = MachineError::functor_stub(clause_name!("sort"), 2);
|
||||||
let list = self.store(self.deref(self[temp_v!(1)].clone()));
|
let list = self.store(self.deref(self[temp_v!(1)].clone()));
|
||||||
let sorted = self.store(self.deref(self[temp_v!(2)].clone()));
|
let sorted = self.store(self.deref(self[temp_v!(2)].clone()));
|
||||||
@@ -447,14 +546,14 @@ impl MachineState {
|
|||||||
return Err(self.error_form(MachineError::instantiation_error(), stub))
|
return Err(self.error_form(MachineError::instantiation_error(), stub))
|
||||||
}
|
}
|
||||||
CycleSearchResult::NotList => {
|
CycleSearchResult::NotList => {
|
||||||
return Err(self.error_form(MachineError::type_error(ValidType::List, list), stub))
|
return Err(self.error_form(MachineError::type_error(0, ValidType::List, list), stub))
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
};
|
};
|
||||||
|
|
||||||
match self.detect_cycles(sorted.clone()) {
|
match self.detect_cycles(sorted.clone()) {
|
||||||
CycleSearchResult::NotList if !sorted.is_ref() => {
|
CycleSearchResult::NotList if !sorted.is_ref() => {
|
||||||
Err(self.error_form(MachineError::type_error(ValidType::List, sorted), stub))
|
Err(self.error_form(MachineError::type_error(0, ValidType::List, sorted), stub))
|
||||||
}
|
}
|
||||||
_ => Ok(()),
|
_ => Ok(()),
|
||||||
}
|
}
|
||||||
@@ -465,7 +564,7 @@ impl MachineState {
|
|||||||
|
|
||||||
match self.detect_cycles(list.clone()) {
|
match self.detect_cycles(list.clone()) {
|
||||||
CycleSearchResult::NotList if !list.is_ref() => {
|
CycleSearchResult::NotList if !list.is_ref() => {
|
||||||
Err(self.error_form(MachineError::type_error(ValidType::List, list), stub))
|
Err(self.error_form(MachineError::type_error(0, ValidType::List, list), stub))
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
let mut addr = list;
|
let mut addr = list;
|
||||||
@@ -474,18 +573,23 @@ impl MachineState {
|
|||||||
let mut new_l = l;
|
let mut new_l = l;
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
match self.heap[new_l].clone() {
|
match self.heap.clone(new_l) {
|
||||||
HeapCellValue::Addr(Addr::Str(l)) => new_l = l,
|
HeapCellValue::Addr(Addr::Str(l)) => {
|
||||||
HeapCellValue::NamedStr(2, ref name, Some(_))
|
new_l = l;
|
||||||
if name.as_str() == "-" =>
|
}
|
||||||
{
|
HeapCellValue::NamedStr(2, ref name, Some(_))
|
||||||
break
|
if name.as_str() == "-" => {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
HeapCellValue::Addr(Addr::HeapCell(_)) => {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
HeapCellValue::Addr(Addr::StackCell(..)) => {
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
HeapCellValue::Addr(Addr::HeapCell(_)) => break,
|
|
||||||
HeapCellValue::Addr(Addr::StackCell(..)) => break,
|
|
||||||
_ => {
|
_ => {
|
||||||
return Err(self.error_form(
|
return Err(self.error_form(
|
||||||
MachineError::type_error(ValidType::Pair, Addr::HeapCell(l)),
|
MachineError::type_error(0, ValidType::Pair, Addr::HeapCell(l)),
|
||||||
stub,
|
stub,
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
@@ -501,9 +605,11 @@ impl MachineState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// see 8.4.4 of Draft Technical Corrigendum 2.
|
// see 8.4.4 of Draft Technical Corrigendum 2.
|
||||||
pub(super) fn check_keysort_errors(&self) -> CallResult {
|
pub(super)
|
||||||
|
fn check_keysort_errors(&self) -> CallResult {
|
||||||
let stub = MachineError::functor_stub(clause_name!("keysort"), 2);
|
let stub = MachineError::functor_stub(clause_name!("keysort"), 2);
|
||||||
let pairs = self.store(self.deref(self[temp_v!(1)].clone()));
|
|
||||||
|
let pairs = self.store(self.deref(self[temp_v!(1)].clone()));
|
||||||
let sorted = self.store(self.deref(self[temp_v!(2)].clone()));
|
let sorted = self.store(self.deref(self[temp_v!(2)].clone()));
|
||||||
|
|
||||||
match self.detect_cycles(pairs.clone()) {
|
match self.detect_cycles(pairs.clone()) {
|
||||||
@@ -511,7 +617,7 @@ impl MachineState {
|
|||||||
Err(self.error_form(MachineError::instantiation_error(), stub))
|
Err(self.error_form(MachineError::instantiation_error(), stub))
|
||||||
}
|
}
|
||||||
CycleSearchResult::NotList => {
|
CycleSearchResult::NotList => {
|
||||||
Err(self.error_form(MachineError::type_error(ValidType::List, pairs), stub))
|
Err(self.error_form(MachineError::type_error(0, ValidType::List, pairs), stub))
|
||||||
}
|
}
|
||||||
_ => Ok(()),
|
_ => Ok(()),
|
||||||
}?;
|
}?;
|
||||||
@@ -519,7 +625,8 @@ impl MachineState {
|
|||||||
self.check_for_list_pairs(sorted)
|
self.check_for_list_pairs(sorted)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn error_form(&self, err: MachineError, src: MachineStub) -> MachineStub {
|
pub(super)
|
||||||
|
fn error_form(&self, err: MachineError, src: MachineStub) -> MachineStub {
|
||||||
let location = err.location;
|
let location = err.location;
|
||||||
let err_len = err.len();
|
let err_len = err.len();
|
||||||
|
|
||||||
@@ -535,21 +642,17 @@ impl MachineState {
|
|||||||
if let Some((line_num, _)) = location {
|
if let Some((line_num, _)) = location {
|
||||||
let colon_op_desc = Some(SharedOpDesc::new(600, XFY));
|
let colon_op_desc = Some(SharedOpDesc::new(600, XFY));
|
||||||
|
|
||||||
stub.extend(
|
stub.push(HeapCellValue::NamedStr(2, clause_name!(":"), colon_op_desc));
|
||||||
vec![
|
stub.push(HeapCellValue::Addr(Addr::HeapCell(h + 6 + err_len)));
|
||||||
HeapCellValue::NamedStr(2, clause_name!(":"), colon_op_desc),
|
stub.push(HeapCellValue::Integer(Rc::new(Integer::from(line_num))));
|
||||||
HeapCellValue::Addr(Addr::HeapCell(h + 6 + err_len)),
|
|
||||||
heap_integer!(Integer::from(line_num)),
|
|
||||||
]
|
|
||||||
.into_iter(),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
stub.extend(src.into_iter());
|
stub.extend(src.into_iter());
|
||||||
stub
|
stub
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn throw_exception(&mut self, err: MachineStub) {
|
pub(super)
|
||||||
|
fn throw_exception(&mut self, err: MachineStub) {
|
||||||
let h = self.heap.h();
|
let h = self.heap.h();
|
||||||
|
|
||||||
self.ball.boundary = 0;
|
self.ball.boundary = 0;
|
||||||
@@ -602,4 +705,5 @@ impl From<ParserError> for EvalSession {
|
|||||||
fn from(err: ParserError) -> Self {
|
fn from(err: ParserError) -> Self {
|
||||||
EvalSession::from(SessionError::ParserError(err))
|
EvalSession::from(SessionError::ParserError(err))
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,11 +7,13 @@ use crate::prolog::forms::*;
|
|||||||
use crate::prolog::machine::code_repo::CodeRepo;
|
use crate::prolog::machine::code_repo::CodeRepo;
|
||||||
use crate::prolog::machine::Ball;
|
use crate::prolog::machine::Ball;
|
||||||
use crate::prolog::machine::heap::*;
|
use crate::prolog::machine::heap::*;
|
||||||
|
use crate::prolog::machine::machine_state::*;
|
||||||
use crate::prolog::machine::partial_string::*;
|
use crate::prolog::machine::partial_string::*;
|
||||||
use crate::prolog::machine::raw_block::RawBlockTraits;
|
use crate::prolog::machine::raw_block::RawBlockTraits;
|
||||||
use crate::prolog::machine::streams::Stream;
|
use crate::prolog::machine::streams::Stream;
|
||||||
use crate::prolog::instructions::*;
|
use crate::prolog::instructions::*;
|
||||||
use crate::prolog::rug::Integer;
|
use crate::prolog::ordered_float::OrderedFloat;
|
||||||
|
use crate::prolog::rug::{Integer, Rational};
|
||||||
|
|
||||||
use indexmap::IndexMap;
|
use indexmap::IndexMap;
|
||||||
|
|
||||||
@@ -39,20 +41,35 @@ pub enum DBRef {
|
|||||||
),
|
),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, PartialEq, Eq, Hash)]
|
// 7.2
|
||||||
pub enum Addr {
|
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
|
||||||
AttrVar(usize),
|
pub enum TermOrderCategory {
|
||||||
Con(Constant),
|
Variable,
|
||||||
DBRef(DBRef),
|
FloatingPoint,
|
||||||
Lis(usize),
|
Integer,
|
||||||
HeapCell(usize),
|
Atom,
|
||||||
StackCell(usize, usize),
|
Compound,
|
||||||
Str(usize),
|
|
||||||
PStrLocation(usize, usize), // location of pstr in heap, offset into string in bytes.
|
|
||||||
Stream(Stream),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, Hash, Eq, PartialEq)]
|
#[derive(Clone, Copy, PartialEq, Eq, Hash)]
|
||||||
|
pub enum Addr {
|
||||||
|
AttrVar(usize),
|
||||||
|
Char(char),
|
||||||
|
CharCode(u32),
|
||||||
|
Con(usize),
|
||||||
|
CutPoint(usize),
|
||||||
|
EmptyList,
|
||||||
|
Float(OrderedFloat<f64>),
|
||||||
|
Lis(usize),
|
||||||
|
HeapCell(usize),
|
||||||
|
PStrLocation(usize, usize), // location of pstr in heap, offset into string in bytes.
|
||||||
|
StackCell(usize, usize),
|
||||||
|
Str(usize),
|
||||||
|
Stream(usize),
|
||||||
|
Usize(usize),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Hash, Eq, PartialEq, PartialOrd)]
|
||||||
pub enum Ref {
|
pub enum Ref {
|
||||||
AttrVar(usize),
|
AttrVar(usize),
|
||||||
HeapCell(usize),
|
HeapCell(usize),
|
||||||
@@ -69,6 +86,28 @@ impl Ref {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Ord for Ref {
|
||||||
|
fn cmp(&self, other: &Ref) -> Ordering {
|
||||||
|
match (self, other) {
|
||||||
|
(Ref::AttrVar(h1), Ref::AttrVar(h2))
|
||||||
|
| (Ref::HeapCell(h1), Ref::HeapCell(h2))
|
||||||
|
| (Ref::HeapCell(h1), Ref::AttrVar(h2))
|
||||||
|
| (Ref::AttrVar(h1), Ref::HeapCell(h2)) => {
|
||||||
|
h1.cmp(&h2)
|
||||||
|
}
|
||||||
|
(Ref::StackCell(fr1, sc1), Ref::StackCell(fr2, sc2)) => {
|
||||||
|
fr1.cmp(&fr2).then_with(|| sc1.cmp(&sc2))
|
||||||
|
}
|
||||||
|
(Ref::StackCell(..), _) => {
|
||||||
|
Ordering::Greater
|
||||||
|
}
|
||||||
|
(_, Ref::StackCell(..)) => {
|
||||||
|
Ordering::Less
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl PartialEq<Ref> for Addr {
|
impl PartialEq<Ref> for Addr {
|
||||||
fn eq(&self, r: &Ref) -> bool {
|
fn eq(&self, r: &Ref) -> bool {
|
||||||
self.as_var() == Some(*r)
|
self.as_var() == Some(*r)
|
||||||
@@ -133,6 +172,83 @@ 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::CharCode(_) | Addr::EmptyList => {
|
||||||
|
Some(TermOrderCategory::Atom)
|
||||||
|
}
|
||||||
|
Addr::Lis(_) | Addr::PStrLocation(..) | Addr::Str(_) => {
|
||||||
|
Some(TermOrderCategory::Compound)
|
||||||
|
}
|
||||||
|
Addr::CutPoint(_) | Addr::Usize(_) | Addr::Stream(_) => {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn as_constant(&self, machine_st: &MachineState) -> Option<Constant> {
|
||||||
|
match self {
|
||||||
|
&Addr::Char(c) => {
|
||||||
|
Some(Constant::Char(c))
|
||||||
|
}
|
||||||
|
&Addr::CharCode(c) => {
|
||||||
|
Some(Constant::CharCode(c))
|
||||||
|
}
|
||||||
|
&Addr::Con(h) => {
|
||||||
|
match &machine_st.heap[h] {
|
||||||
|
&HeapCellValue::Atom(ref name, ref op) => {
|
||||||
|
Some(Constant::Atom(name.clone(), op.clone()))
|
||||||
|
}
|
||||||
|
&HeapCellValue::Integer(ref n) => {
|
||||||
|
Some(Constant::Integer(n.clone()))
|
||||||
|
}
|
||||||
|
&HeapCellValue::Rational(ref n) => {
|
||||||
|
Some(Constant::Rational(n.clone()))
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&Addr::Float(f) => {
|
||||||
|
Some(Constant::Float(f))
|
||||||
|
}
|
||||||
|
&Addr::PStrLocation(h, n) => {
|
||||||
|
machine_st.to_complete_string(h, n)
|
||||||
|
.map(|s| Constant::String(Rc::new(s)))
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn is_protected(&self, e: usize) -> bool {
|
pub fn is_protected(&self, e: usize) -> bool {
|
||||||
match self {
|
match self {
|
||||||
&Addr::StackCell(addr, _) if addr >= e => false,
|
&Addr::StackCell(addr, _) if addr >= e => false,
|
||||||
@@ -209,27 +325,76 @@ impl From<Ref> for TrailRef {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, PartialEq)]
|
|
||||||
pub enum HeapCellValue {
|
pub enum HeapCellValue {
|
||||||
Addr(Addr),
|
Addr(Addr),
|
||||||
|
Atom(ClauseName, Option<SharedOpDesc>),
|
||||||
|
DBRef(DBRef),
|
||||||
|
Integer(Rc<Integer>),
|
||||||
NamedStr(usize, ClauseName, Option<SharedOpDesc>), // arity, name, precedence/Specifier if it has one.
|
NamedStr(usize, ClauseName, Option<SharedOpDesc>), // arity, name, precedence/Specifier if it has one.
|
||||||
|
Rational(Rc<Rational>),
|
||||||
PartialString(PartialString),
|
PartialString(PartialString),
|
||||||
|
Stream(Stream),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl HeapCellValue {
|
impl HeapCellValue {
|
||||||
|
#[inline]
|
||||||
pub fn as_addr(&self, focus: usize) -> Addr {
|
pub fn as_addr(&self, focus: usize) -> Addr {
|
||||||
match self {
|
match self {
|
||||||
HeapCellValue::Addr(ref a) => {
|
HeapCellValue::Addr(ref a) => {
|
||||||
a.clone()
|
a.clone()
|
||||||
}
|
}
|
||||||
|
HeapCellValue::Atom(..) | HeapCellValue::DBRef(..) | HeapCellValue::Integer(..) |
|
||||||
|
HeapCellValue::Rational(..) => {
|
||||||
|
Addr::Con(focus)
|
||||||
|
}
|
||||||
HeapCellValue::NamedStr(_, _, _) => {
|
HeapCellValue::NamedStr(_, _, _) => {
|
||||||
Addr::Str(focus)
|
Addr::Str(focus)
|
||||||
}
|
}
|
||||||
HeapCellValue::PartialString(_) => {
|
HeapCellValue::PartialString(_) => {
|
||||||
Addr::PStrLocation(focus, 0)
|
Addr::PStrLocation(focus, 0)
|
||||||
}
|
}
|
||||||
|
HeapCellValue::Stream(_) => {
|
||||||
|
Addr::Stream(focus)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn context_free_clone(&self) -> HeapCellValue {
|
||||||
|
match self {
|
||||||
|
&HeapCellValue::Addr(addr) => {
|
||||||
|
HeapCellValue::Addr(addr)
|
||||||
|
}
|
||||||
|
&HeapCellValue::Atom(ref name, ref op) => {
|
||||||
|
HeapCellValue::Atom(name.clone(), op.clone())
|
||||||
|
}
|
||||||
|
&HeapCellValue::DBRef(ref db_ref) => {
|
||||||
|
HeapCellValue::DBRef(db_ref.clone())
|
||||||
|
}
|
||||||
|
&HeapCellValue::Integer(ref n) => {
|
||||||
|
HeapCellValue::Integer(n.clone())
|
||||||
|
}
|
||||||
|
&HeapCellValue::NamedStr(arity, ref name, ref op) => {
|
||||||
|
HeapCellValue::NamedStr(arity, name.clone(), op.clone())
|
||||||
|
}
|
||||||
|
&HeapCellValue::Rational(ref r) => {
|
||||||
|
HeapCellValue::Rational(r.clone())
|
||||||
|
}
|
||||||
|
&HeapCellValue::PartialString(ref pstr) => {
|
||||||
|
HeapCellValue::PartialString(pstr.clone())
|
||||||
|
}
|
||||||
|
&HeapCellValue::Stream(_) => {
|
||||||
|
HeapCellValue::Stream(Stream::null_stream())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Addr> for HeapCellValue {
|
||||||
|
#[inline]
|
||||||
|
fn from(value: Addr) -> HeapCellValue {
|
||||||
|
HeapCellValue::Addr(value)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, Eq, PartialEq, Ord, PartialOrd)]
|
#[derive(Clone, Copy, Eq, PartialEq, Ord, PartialOrd)]
|
||||||
@@ -407,37 +572,31 @@ impl LocalCodePtr {
|
|||||||
LocalCodePtr::DirEntry(p) => {
|
LocalCodePtr::DirEntry(p) => {
|
||||||
heap.append(functor!(
|
heap.append(functor!(
|
||||||
"dir_entry",
|
"dir_entry",
|
||||||
1,
|
[integer(*p)]
|
||||||
[heap_integer!(Integer::from(*p))]
|
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
LocalCodePtr::InSituDirEntry(p) => {
|
LocalCodePtr::InSituDirEntry(p) => {
|
||||||
heap.append(functor!(
|
heap.append(functor!(
|
||||||
"in_situ_dir_entry",
|
"in_situ_dir_entry",
|
||||||
1,
|
[integer(*p)]
|
||||||
[heap_integer!(Integer::from(*p))]
|
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
LocalCodePtr::TopLevel(chunk_num, offset) => {
|
LocalCodePtr::TopLevel(chunk_num, offset) => {
|
||||||
heap.append(functor!(
|
heap.append(functor!(
|
||||||
"top_level",
|
"top_level",
|
||||||
2,
|
[integer(*chunk_num), integer(*offset)]
|
||||||
[heap_integer!(Integer::from(*chunk_num)),
|
|
||||||
heap_integer!(Integer::from(*offset))]
|
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
LocalCodePtr::UserGoalExpansion(p) => {
|
LocalCodePtr::UserGoalExpansion(p) => {
|
||||||
heap.append(functor!(
|
heap.append(functor!(
|
||||||
"user_goal_expansion",
|
"user_goal_expansion",
|
||||||
1,
|
[integer(*p)]
|
||||||
[heap_integer!(Integer::from(*p))]
|
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
LocalCodePtr::UserTermExpansion(p) => {
|
LocalCodePtr::UserTermExpansion(p) => {
|
||||||
heap.append(functor!(
|
heap.append(functor!(
|
||||||
"user_term_expansion",
|
"user_term_expansion",
|
||||||
1,
|
[integer(*p)]
|
||||||
[heap_integer!(Integer::from(*p))]
|
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -449,8 +608,12 @@ impl LocalCodePtr {
|
|||||||
impl PartialOrd<CodePtr> for CodePtr {
|
impl PartialOrd<CodePtr> for CodePtr {
|
||||||
fn partial_cmp(&self, other: &CodePtr) -> Option<Ordering> {
|
fn partial_cmp(&self, other: &CodePtr) -> Option<Ordering> {
|
||||||
match (self, other) {
|
match (self, other) {
|
||||||
(&CodePtr::Local(ref l1), &CodePtr::Local(ref l2)) => l1.partial_cmp(l2),
|
(&CodePtr::Local(ref l1), &CodePtr::Local(ref l2)) => {
|
||||||
_ => Some(Ordering::Greater),
|
l1.partial_cmp(l2)
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
Some(Ordering::Greater)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -465,8 +628,12 @@ impl PartialOrd<LocalCodePtr> for LocalCodePtr {
|
|||||||
| (&LocalCodePtr::TopLevel(_, p1), &LocalCodePtr::TopLevel(_, ref p2)) => {
|
| (&LocalCodePtr::TopLevel(_, p1), &LocalCodePtr::TopLevel(_, ref p2)) => {
|
||||||
p1.partial_cmp(p2)
|
p1.partial_cmp(p2)
|
||||||
}
|
}
|
||||||
(_, &LocalCodePtr::TopLevel(_, _)) => Some(Ordering::Less),
|
(_, &LocalCodePtr::TopLevel(_, _)) => {
|
||||||
_ => Some(Ordering::Greater),
|
Some(Ordering::Less)
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
Some(Ordering::Greater)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,7 +18,6 @@ use std::cmp::Ordering;
|
|||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
use std::mem;
|
use std::mem;
|
||||||
use std::ops::{Index, IndexMut};
|
use std::ops::{Index, IndexMut};
|
||||||
use std::rc::Rc;
|
|
||||||
|
|
||||||
pub struct Ball {
|
pub struct Ball {
|
||||||
pub(super) boundary: usize,
|
pub(super) boundary: usize,
|
||||||
@@ -58,11 +57,11 @@ impl Ball {
|
|||||||
|
|
||||||
for heap_value in self.stub.iter_from(0) {
|
for heap_value in self.stub.iter_from(0) {
|
||||||
stub.push(match heap_value {
|
stub.push(match heap_value {
|
||||||
HeapCellValue::Addr(ref addr) => {
|
&HeapCellValue::Addr(addr) => {
|
||||||
HeapCellValue::Addr(addr.clone() - diff)
|
HeapCellValue::Addr(addr - diff)
|
||||||
}
|
}
|
||||||
heap_value => {
|
heap_value => {
|
||||||
heap_value.clone()
|
heap_value.context_free_clone()
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -185,8 +184,12 @@ impl<'a> CopierTarget for CopyBallTerm<'a> {
|
|||||||
let index = h - self.heap_boundary;
|
let index = h - self.heap_boundary;
|
||||||
self.stub[index].as_addr(h)
|
self.stub[index].as_addr(h)
|
||||||
}
|
}
|
||||||
Addr::StackCell(fr, sc) => self.stack.index_and_frame(fr)[sc].clone(),
|
Addr::StackCell(fr, sc) => {
|
||||||
addr => addr,
|
self.stack.index_and_frame(fr)[sc].clone()
|
||||||
|
}
|
||||||
|
addr => {
|
||||||
|
addr
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -250,8 +253,6 @@ pub(super) enum HeapPtr {
|
|||||||
HeapCell(usize),
|
HeapCell(usize),
|
||||||
PStrChar(usize, usize),
|
PStrChar(usize, usize),
|
||||||
PStrLocation(usize, usize),
|
PStrLocation(usize, usize),
|
||||||
StringChar(usize, Rc<String>),
|
|
||||||
StringLocation(usize, Rc<String>),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl HeapPtr {
|
impl HeapPtr {
|
||||||
@@ -259,30 +260,23 @@ impl HeapPtr {
|
|||||||
pub(super)
|
pub(super)
|
||||||
fn read(&self, heap: &Heap) -> Addr {
|
fn read(&self, heap: &Heap) -> Addr {
|
||||||
match self {
|
match self {
|
||||||
&HeapPtr::HeapCell(h) =>
|
&HeapPtr::HeapCell(h) => {
|
||||||
Addr::HeapCell(h),
|
Addr::HeapCell(h)
|
||||||
&HeapPtr::PStrChar(h, n) =>
|
}
|
||||||
|
&HeapPtr::PStrChar(h, n) => {
|
||||||
if let HeapCellValue::PartialString(ref pstr) = &heap[h] {
|
if let HeapCellValue::PartialString(ref pstr) = &heap[h] {
|
||||||
let s = pstr.block_as_str();
|
if let Some(c) = pstr.range_from(n ..).next() {
|
||||||
|
Addr::Char(c)
|
||||||
if let Some(c) = s[n ..].chars().next() {
|
|
||||||
Addr::Con(Constant::Char(c))
|
|
||||||
} else {
|
} else {
|
||||||
Addr::HeapCell(h + 1)
|
Addr::HeapCell(h + 1)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
},
|
}
|
||||||
&HeapPtr::PStrLocation(h, n) =>
|
}
|
||||||
Addr::PStrLocation(h, n),
|
&HeapPtr::PStrLocation(h, n) => {
|
||||||
&HeapPtr::StringChar(n, ref s) =>
|
Addr::PStrLocation(h, n)
|
||||||
if let Some(c) = s[n ..].chars().next() {
|
}
|
||||||
Addr::Con(Constant::Char(c))
|
|
||||||
} else {
|
|
||||||
Addr::Con(Constant::EmptyList)
|
|
||||||
},
|
|
||||||
&HeapPtr::StringLocation(n, ref s) =>
|
|
||||||
Addr::Con(Constant::String(n, s.clone())),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -330,29 +324,27 @@ impl MachineState {
|
|||||||
let addr = self.store(self.deref(addr.clone()));
|
let addr = self.store(self.deref(addr.clone()));
|
||||||
|
|
||||||
match addr {
|
match addr {
|
||||||
Addr::Con(Constant::String(n, ref s))
|
Addr::Char(c) => {
|
||||||
if self.flags.double_quotes.is_chars() => {
|
|
||||||
if s.len() < n {
|
|
||||||
chars += &s[n ..];
|
|
||||||
}
|
|
||||||
|
|
||||||
if iter.next().is_some() {
|
|
||||||
return Err(MachineError::type_error(ValidType::Character, addr.clone()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Addr::Con(Constant::Char(c)) => {
|
|
||||||
chars.push(c);
|
chars.push(c);
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
Addr::Con(Constant::Atom(ref name, _))
|
Addr::Con(h) => {
|
||||||
if name.as_str().len() == 1 => {
|
if let HeapCellValue::Atom(ref name, _) = &self.heap[h] {
|
||||||
chars += name.as_str();
|
if name.is_char() {
|
||||||
|
chars += name.as_str();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
_ => {
|
|
||||||
return Err(
|
|
||||||
MachineError::type_error(ValidType::Character, addr.clone())
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
_ => {
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let h = self.heap.h();
|
||||||
|
|
||||||
|
return Err(
|
||||||
|
MachineError::type_error(h, ValidType::Character, addr)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(chars)
|
Ok(chars)
|
||||||
@@ -738,32 +730,36 @@ pub(crate) trait CallPolicy: Any {
|
|||||||
let a2 = machine_st[temp_v!(2)].clone();
|
let a2 = machine_st[temp_v!(2)].clone();
|
||||||
let a3 = machine_st[temp_v!(3)].clone();
|
let a3 = machine_st[temp_v!(3)].clone();
|
||||||
|
|
||||||
let c = match machine_st.compare_term_test(&a2, &a3) {
|
let atom = match machine_st.compare_term_test(&a2, &a3) {
|
||||||
Ordering::Greater => {
|
Some(Ordering::Greater) => {
|
||||||
let spec = fetch_atom_op_spec(clause_name!(">"), None, &indices.op_dir);
|
let spec = fetch_atom_op_spec(clause_name!(">"), None, &indices.op_dir);
|
||||||
Addr::Con(Constant::Atom(clause_name!(">"), spec))
|
HeapCellValue::Atom(clause_name!(">"), spec)
|
||||||
}
|
}
|
||||||
Ordering::Equal => {
|
Some(Ordering::Equal) => {
|
||||||
let spec = fetch_atom_op_spec(clause_name!("="), None, &indices.op_dir);
|
let spec = fetch_atom_op_spec(clause_name!("="), None, &indices.op_dir);
|
||||||
Addr::Con(Constant::Atom(clause_name!("="), spec))
|
HeapCellValue::Atom(clause_name!("="), spec)
|
||||||
}
|
}
|
||||||
Ordering::Less => {
|
None | Some(Ordering::Less) => {
|
||||||
let spec = fetch_atom_op_spec(clause_name!("<"), None, &indices.op_dir);
|
let spec = fetch_atom_op_spec(clause_name!("<"), None, &indices.op_dir);
|
||||||
Addr::Con(Constant::Atom(clause_name!("<"), spec))
|
HeapCellValue::Atom(clause_name!("<"), spec)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
machine_st.unify(a1, c);
|
let h = machine_st.heap.h();
|
||||||
|
|
||||||
|
machine_st.heap.push(atom);
|
||||||
|
machine_st.unify(a1, Addr::Con(h));
|
||||||
|
|
||||||
return_from_clause!(machine_st.last_call, machine_st)
|
return_from_clause!(machine_st.last_call, machine_st)
|
||||||
}
|
}
|
||||||
&BuiltInClauseType::CompareTerm(qt) => {
|
&BuiltInClauseType::CompareTerm(qt) => {
|
||||||
machine_st.compare_term(qt);
|
machine_st.compare_term(qt);
|
||||||
return_from_clause!(machine_st.last_call, machine_st)
|
return_from_clause!(machine_st.last_call, machine_st)
|
||||||
}
|
}
|
||||||
&BuiltInClauseType::Nl => {
|
&BuiltInClauseType::Nl => {
|
||||||
write!(current_output_stream, "\n").unwrap();
|
write!(current_output_stream, "\n").unwrap();
|
||||||
current_output_stream.flush().unwrap();
|
current_output_stream.flush().unwrap();
|
||||||
|
|
||||||
return_from_clause!(machine_st.last_call, machine_st)
|
return_from_clause!(machine_st.last_call, machine_st)
|
||||||
}
|
}
|
||||||
&BuiltInClauseType::Read => {
|
&BuiltInClauseType::Read => {
|
||||||
@@ -811,11 +807,12 @@ pub(crate) trait CallPolicy: Any {
|
|||||||
let a1 = machine_st[temp_v!(1)].clone();
|
let a1 = machine_st[temp_v!(1)].clone();
|
||||||
let a2 = machine_st[temp_v!(2)].clone();
|
let a2 = machine_st[temp_v!(2)].clone();
|
||||||
|
|
||||||
machine_st.fail = if let Ordering::Equal = machine_st.compare_term_test(&a1, &a2) {
|
machine_st.fail =
|
||||||
true
|
if let Some(Ordering::Equal) = machine_st.compare_term_test(&a1, &a2) {
|
||||||
} else {
|
true
|
||||||
false
|
} else {
|
||||||
};
|
false
|
||||||
|
};
|
||||||
|
|
||||||
return_from_clause!(machine_st.last_call, machine_st)
|
return_from_clause!(machine_st.last_call, machine_st)
|
||||||
}
|
}
|
||||||
@@ -825,7 +822,10 @@ pub(crate) trait CallPolicy: Any {
|
|||||||
let stub = MachineError::functor_stub(clause_name!("sort"), 2);
|
let stub = MachineError::functor_stub(clause_name!("sort"), 2);
|
||||||
let mut list = machine_st.try_from_list(temp_v!(1), stub)?;
|
let mut list = machine_st.try_from_list(temp_v!(1), stub)?;
|
||||||
|
|
||||||
list.sort_unstable_by(|a1, a2| machine_st.compare_term_test(a1, a2));
|
list.sort_unstable_by(|a1, a2| {
|
||||||
|
machine_st.compare_term_test(a1, a2).unwrap_or(Ordering::Less)
|
||||||
|
});
|
||||||
|
|
||||||
machine_st.term_dedup(&mut list);
|
machine_st.term_dedup(&mut list);
|
||||||
|
|
||||||
let heap_addr = Addr::HeapCell(machine_st.heap.to_list(list.into_iter()));
|
let heap_addr = Addr::HeapCell(machine_st.heap.to_list(list.into_iter()));
|
||||||
@@ -847,7 +847,9 @@ pub(crate) trait CallPolicy: Any {
|
|||||||
key_pairs.push((key, val.clone()));
|
key_pairs.push((key, val.clone()));
|
||||||
}
|
}
|
||||||
|
|
||||||
key_pairs.sort_by(|a1, a2| machine_st.compare_term_test(&a1.0, &a2.0));
|
key_pairs.sort_by(|a1, a2| {
|
||||||
|
machine_st.compare_term_test(&a1.0, &a2.0).unwrap_or(Ordering::Less)
|
||||||
|
});
|
||||||
|
|
||||||
let key_pairs = key_pairs.into_iter().map(|kp| kp.1);
|
let key_pairs = key_pairs.into_iter().map(|kp| kp.1);
|
||||||
let heap_addr = Addr::HeapCell(machine_st.heap.to_list(key_pairs));
|
let heap_addr = Addr::HeapCell(machine_st.heap.to_list(key_pairs));
|
||||||
@@ -859,9 +861,11 @@ pub(crate) trait CallPolicy: Any {
|
|||||||
}
|
}
|
||||||
&BuiltInClauseType::Is(r, ref at) => {
|
&BuiltInClauseType::Is(r, ref at) => {
|
||||||
let a1 = machine_st[r].clone();
|
let a1 = machine_st[r].clone();
|
||||||
let a2 = machine_st.get_number(at)?;
|
let n2 = machine_st.get_number(at)?;
|
||||||
|
|
||||||
|
let n2 = Addr::Con(machine_st.heap.push(n2.into()));
|
||||||
|
machine_st.unify(a1, n2);
|
||||||
|
|
||||||
machine_st.unify(a1, Addr::Con(a2.to_constant()));
|
|
||||||
return_from_clause!(machine_st.last_call, machine_st)
|
return_from_clause!(machine_st.last_call, machine_st)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -935,11 +939,13 @@ pub(crate) trait CallPolicy: Any {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
ClauseType::Hook(_) | ClauseType::System(_) => {
|
ClauseType::Hook(_) | ClauseType::System(_) => {
|
||||||
let name = Addr::Con(Constant::Atom(name, None));
|
let name = functor!(clause_name(name));
|
||||||
let stub = MachineError::functor_stub(clause_name!("call"), arity + 1);
|
let stub = MachineError::functor_stub(clause_name!("call"), arity + 1);
|
||||||
|
|
||||||
return Err(machine_st
|
return Err(machine_st.error_form(
|
||||||
.error_form(MachineError::type_error(ValidType::Callable, name), stub));
|
MachineError::type_error(machine_st.heap.h(), ValidType::Callable, name),
|
||||||
|
stub,
|
||||||
|
));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -997,7 +1003,7 @@ impl CallPolicy for CWILCallPolicy {
|
|||||||
current_input_stream,
|
current_input_stream,
|
||||||
current_output_stream
|
current_output_stream
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
self.increment(machine_st)
|
self.increment(machine_st)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1016,7 +1022,7 @@ impl CallPolicy for CWILCallPolicy {
|
|||||||
current_input_stream,
|
current_input_stream,
|
||||||
current_output_stream,
|
current_output_stream,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
self.increment(machine_st)
|
self.increment(machine_st)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1035,7 +1041,8 @@ pub(crate) struct CWILCallPolicy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl CWILCallPolicy {
|
impl CWILCallPolicy {
|
||||||
pub(crate) fn new_in_place(policy: &mut Box<dyn CallPolicy>) {
|
pub(crate)
|
||||||
|
fn new_in_place(policy: &mut Box<dyn CallPolicy>) {
|
||||||
let mut prev_policy: Box<dyn CallPolicy> = Box::new(DefaultCallPolicy {});
|
let mut prev_policy: Box<dyn CallPolicy> = Box::new(DefaultCallPolicy {});
|
||||||
mem::swap(&mut prev_policy, policy);
|
mem::swap(&mut prev_policy, policy);
|
||||||
|
|
||||||
@@ -1045,6 +1052,7 @@ impl CWILCallPolicy {
|
|||||||
limits: vec![],
|
limits: vec![],
|
||||||
inference_limit_exceeded: false,
|
inference_limit_exceeded: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
*policy = Box::new(new_policy);
|
*policy = Box::new(new_policy);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1056,10 +1064,10 @@ impl CWILCallPolicy {
|
|||||||
if let Some(&(ref limit, bp)) = self.limits.last() {
|
if let Some(&(ref limit, bp)) = self.limits.last() {
|
||||||
if self.count == *limit {
|
if self.count == *limit {
|
||||||
self.inference_limit_exceeded = true;
|
self.inference_limit_exceeded = true;
|
||||||
|
|
||||||
return Err(functor!(
|
return Err(functor!(
|
||||||
"inference_limit_exceeded",
|
"inference_limit_exceeded",
|
||||||
1,
|
[addr(Addr::Usize(bp))]
|
||||||
[HeapCellValue::Addr(Addr::Con(Constant::Usize(bp)))]
|
|
||||||
));
|
));
|
||||||
} else {
|
} else {
|
||||||
self.count += 1;
|
self.count += 1;
|
||||||
@@ -1069,7 +1077,8 @@ impl CWILCallPolicy {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn add_limit(&mut self, mut limit: Integer, b: usize) -> &Integer {
|
pub(crate)
|
||||||
|
fn add_limit(&mut self, mut limit: Integer, b: usize) -> &Integer {
|
||||||
limit += &self.count;
|
limit += &self.count;
|
||||||
|
|
||||||
match self.limits.last().cloned() {
|
match self.limits.last().cloned() {
|
||||||
@@ -1080,7 +1089,8 @@ impl CWILCallPolicy {
|
|||||||
&self.count
|
&self.count
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn remove_limit(&mut self, b: usize) -> &Integer {
|
pub(crate)
|
||||||
|
fn remove_limit(&mut self, b: usize) -> &Integer {
|
||||||
if let Some((_, bp)) = self.limits.last().cloned() {
|
if let Some((_, bp)) = self.limits.last().cloned() {
|
||||||
if bp == b {
|
if bp == b {
|
||||||
self.limits.pop();
|
self.limits.pop();
|
||||||
@@ -1090,11 +1100,13 @@ impl CWILCallPolicy {
|
|||||||
&self.count
|
&self.count
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn is_empty(&self) -> bool {
|
pub(crate)
|
||||||
|
fn is_empty(&self) -> bool {
|
||||||
self.limits.is_empty()
|
self.limits.is_empty()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn into_inner(&mut self) -> Box<dyn CallPolicy> {
|
pub(crate)
|
||||||
|
fn into_inner(&mut self) -> Box<dyn CallPolicy> {
|
||||||
let mut new_inner: Box<dyn CallPolicy> = Box::new(DefaultCallPolicy {});
|
let mut new_inner: Box<dyn CallPolicy> = Box::new(DefaultCallPolicy {});
|
||||||
mem::swap(&mut self.prev_policy, &mut new_inner);
|
mem::swap(&mut self.prev_policy, &mut new_inner);
|
||||||
new_inner
|
new_inner
|
||||||
@@ -1108,11 +1120,11 @@ pub(crate) trait CutPolicy: Any {
|
|||||||
|
|
||||||
downcast!(dyn CutPolicy);
|
downcast!(dyn CutPolicy);
|
||||||
|
|
||||||
fn cut_body(machine_st: &mut MachineState, addr: Addr) -> bool {
|
fn cut_body(machine_st: &mut MachineState, addr: &Addr) -> bool {
|
||||||
let b = machine_st.b;
|
let b = machine_st.b;
|
||||||
|
|
||||||
match addr {
|
match addr {
|
||||||
Addr::Con(Constant::CutPoint(b0)) | Addr::Con(Constant::Usize(b0)) => {
|
&Addr::CutPoint(b0) | &Addr::Usize(b0) => {
|
||||||
if b > b0 {
|
if b > b0 {
|
||||||
machine_st.b = b0;
|
machine_st.b = b0;
|
||||||
machine_st.tidy_trail();
|
machine_st.tidy_trail();
|
||||||
@@ -1131,13 +1143,13 @@ pub(crate) struct DefaultCutPolicy {}
|
|||||||
|
|
||||||
pub(super) fn deref_cut(machine_st: &mut MachineState, r: RegType) {
|
pub(super) fn deref_cut(machine_st: &mut MachineState, r: RegType) {
|
||||||
let addr = machine_st.store(machine_st.deref(machine_st[r].clone()));
|
let addr = machine_st.store(machine_st.deref(machine_st[r].clone()));
|
||||||
cut_body(machine_st, addr);
|
cut_body(machine_st, &addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CutPolicy for DefaultCutPolicy {
|
impl CutPolicy for DefaultCutPolicy {
|
||||||
fn cut(&mut self, machine_st: &mut MachineState, r: RegType) -> bool {
|
fn cut(&mut self, machine_st: &mut MachineState, r: RegType) -> bool {
|
||||||
let addr = machine_st[r].clone();
|
let addr = machine_st[r].clone();
|
||||||
cut_body(machine_st, addr)
|
cut_body(machine_st, &addr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1175,7 +1187,7 @@ impl SCCCutPolicy {
|
|||||||
let (idx, arity) = if machine_st.block < prev_block {
|
let (idx, arity) = if machine_st.block < prev_block {
|
||||||
(dir_entry!(self.r_c_w_h), 0)
|
(dir_entry!(self.r_c_w_h), 0)
|
||||||
} else {
|
} else {
|
||||||
machine_st[temp_v!(1)] = Addr::Con(Constant::Usize(b_cutoff));
|
machine_st[temp_v!(1)] = Addr::Usize(b_cutoff);
|
||||||
(dir_entry!(self.r_c_wo_h), 1)
|
(dir_entry!(self.r_c_wo_h), 1)
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1198,7 +1210,7 @@ impl CutPolicy for SCCCutPolicy {
|
|||||||
let b = machine_st.b;
|
let b = machine_st.b;
|
||||||
|
|
||||||
match machine_st[r].clone() {
|
match machine_st[r].clone() {
|
||||||
Addr::Con(Constant::Usize(b0)) | Addr::Con(Constant::CutPoint(b0)) => {
|
Addr::Usize(b0) | Addr::CutPoint(b0) => {
|
||||||
if b > b0 {
|
if b > b0 {
|
||||||
machine_st.b = b0;
|
machine_st.b = b0;
|
||||||
machine_st.tidy_trail();
|
machine_st.tidy_trail();
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -19,13 +19,15 @@ pub mod machine_errors;
|
|||||||
pub mod machine_indices;
|
pub mod machine_indices;
|
||||||
pub(super) mod machine_state;
|
pub(super) mod machine_state;
|
||||||
pub mod modules;
|
pub mod modules;
|
||||||
mod partial_string;
|
pub mod partial_string;
|
||||||
mod raw_block;
|
mod raw_block;
|
||||||
mod stack;
|
mod stack;
|
||||||
pub(crate) mod streams;
|
pub(crate) mod streams;
|
||||||
pub(super) mod term_expansion;
|
pub(super) mod term_expansion;
|
||||||
pub mod toplevel;
|
pub mod toplevel;
|
||||||
|
|
||||||
|
#[macro_use]
|
||||||
|
mod arithmetic_ops;
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
mod machine_state_impl;
|
mod machine_state_impl;
|
||||||
mod system_calls;
|
mod system_calls;
|
||||||
@@ -340,8 +342,8 @@ impl Machine {
|
|||||||
// the first of these is the path to the scryer-prolog executable, so skip
|
// the first of these is the path to the scryer-prolog executable, so skip
|
||||||
// it.
|
// it.
|
||||||
for filename in env::args().skip(1) {
|
for filename in env::args().skip(1) {
|
||||||
let atom = atom!(filename, self.indices.atom_tbl);
|
let atom = clause_name!(filename, self.indices.atom_tbl);
|
||||||
filename_atoms.push(Addr::Con(atom));
|
filename_atoms.push(HeapCellValue::Atom(atom, None));
|
||||||
}
|
}
|
||||||
|
|
||||||
let list_addr =
|
let list_addr =
|
||||||
@@ -547,14 +549,14 @@ impl Machine {
|
|||||||
HeapCellValue::NamedStr(arity, ref name, _)
|
HeapCellValue::NamedStr(arity, ref name, _)
|
||||||
if *arity == 2 && name.as_str() == "/" => {
|
if *arity == 2 && name.as_str() == "/" => {
|
||||||
let name = match &self.machine_st.heap[s+1] {
|
let name = match &self.machine_st.heap[s+1] {
|
||||||
&HeapCellValue::Addr(Addr::Con(Constant::Atom(ref name, _))) =>
|
&HeapCellValue::Atom(ref name, _) =>
|
||||||
name.clone(),
|
name.clone(),
|
||||||
_ =>
|
_ =>
|
||||||
unreachable!()
|
unreachable!()
|
||||||
};
|
};
|
||||||
|
|
||||||
let arity = match &self.machine_st.heap[s+2] {
|
let arity = match &self.machine_st.heap[s+2] {
|
||||||
&HeapCellValue::Addr(Addr::Con(Constant::Integer(ref arity))) =>
|
&HeapCellValue::Integer(ref arity) =>
|
||||||
arity.to_usize().unwrap(),
|
arity.to_usize().unwrap(),
|
||||||
_ =>
|
_ =>
|
||||||
unreachable!()
|
unreachable!()
|
||||||
@@ -565,21 +567,21 @@ impl Machine {
|
|||||||
HeapCellValue::NamedStr(arity, ref name, _)
|
HeapCellValue::NamedStr(arity, ref name, _)
|
||||||
if *arity == 3 && name.as_str() == "op" => {
|
if *arity == 3 && name.as_str() == "op" => {
|
||||||
let name = match &self.machine_st.heap[s+3] {
|
let name = match &self.machine_st.heap[s+3] {
|
||||||
&HeapCellValue::Addr(Addr::Con(Constant::Atom(ref name, _))) =>
|
&HeapCellValue::Atom(ref name, _) =>
|
||||||
name.clone(),
|
name.clone(),
|
||||||
_ =>
|
_ =>
|
||||||
unreachable!()
|
unreachable!()
|
||||||
};
|
};
|
||||||
|
|
||||||
let spec = match &self.machine_st.heap[s+2] {
|
let spec = match &self.machine_st.heap[s+2] {
|
||||||
&HeapCellValue::Addr(Addr::Con(Constant::Atom(ref name, _))) =>
|
&HeapCellValue::Atom(ref name, _) =>
|
||||||
name.clone(),
|
name.clone(),
|
||||||
_ =>
|
_ =>
|
||||||
unreachable!()
|
unreachable!()
|
||||||
};
|
};
|
||||||
|
|
||||||
let prec = match &self.machine_st.heap[s+1] {
|
let prec = match &self.machine_st.heap[s+1] {
|
||||||
&HeapCellValue::Addr(Addr::Con(Constant::Integer(ref arity))) =>
|
&HeapCellValue::Integer(ref arity) =>
|
||||||
arity.to_usize().unwrap(),
|
arity.to_usize().unwrap(),
|
||||||
_ =>
|
_ =>
|
||||||
unreachable!()
|
unreachable!()
|
||||||
@@ -610,9 +612,13 @@ impl Machine {
|
|||||||
let cached_query = mem::replace(&mut self.code_repo.cached_query, vec![]);
|
let cached_query = mem::replace(&mut self.code_repo.cached_query, vec![]);
|
||||||
|
|
||||||
let module_spec = self.machine_st[temp_v!(1)].clone();
|
let module_spec = self.machine_st[temp_v!(1)].clone();
|
||||||
let name = match self.machine_st.store(self.machine_st.deref(module_spec)) {
|
let name = {
|
||||||
Addr::Con(Constant::Atom(name, _)) => name,
|
let addr = self.machine_st.store(self.machine_st.deref(module_spec));
|
||||||
_ => unreachable!()
|
|
||||||
|
match self.machine_st.heap.index_addr(&addr).as_ref() {
|
||||||
|
HeapCellValue::Atom(name, _) => name.clone(),
|
||||||
|
_ => unreachable!(),
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let load_result = match to_src(name) {
|
let load_result = match to_src(name) {
|
||||||
@@ -653,9 +659,13 @@ impl Machine {
|
|||||||
let cached_query = mem::replace(&mut self.code_repo.cached_query, vec![]);
|
let cached_query = mem::replace(&mut self.code_repo.cached_query, vec![]);
|
||||||
|
|
||||||
let module_spec = self.machine_st[temp_v!(1)].clone();
|
let module_spec = self.machine_st[temp_v!(1)].clone();
|
||||||
let name = match self.machine_st.store(self.machine_st.deref(module_spec)) {
|
let name = {
|
||||||
Addr::Con(Constant::Atom(name, _)) => name,
|
let addr = self.machine_st.store(self.machine_st.deref(module_spec));
|
||||||
_ => unreachable!()
|
|
||||||
|
match self.machine_st.heap.index_addr(&addr).as_ref() {
|
||||||
|
HeapCellValue::Atom(name, _) => name.clone(),
|
||||||
|
_ => unreachable!(),
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let exports = match self.extract_module_export_list() {
|
let exports = match self.extract_module_export_list() {
|
||||||
|
|||||||
@@ -1,26 +1,11 @@
|
|||||||
use crate::prolog::machine::raw_block::*;
|
use std::alloc;
|
||||||
|
|
||||||
use std::mem;
|
use std::mem;
|
||||||
use std::ptr;
|
use std::ptr;
|
||||||
use std::slice;
|
use std::ops::{Range, RangeFrom};
|
||||||
use std::str;
|
use std::str;
|
||||||
|
|
||||||
pub(crate) struct PartialStringTraits {}
|
|
||||||
|
|
||||||
impl RawBlockTraits for PartialStringTraits {
|
|
||||||
#[inline]
|
|
||||||
fn init_size() -> usize {
|
|
||||||
0
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn align() -> usize {
|
|
||||||
mem::align_of::<char>()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct PartialString {
|
pub struct PartialString {
|
||||||
pub(super) buf: RawBlock<PartialStringTraits>,
|
buf: *const u8,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Clone for PartialString {
|
impl Clone for PartialString {
|
||||||
@@ -30,17 +15,10 @@ impl Clone for PartialString {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PartialEq for PartialString {
|
fn scan_for_terminator<Iter: Iterator<Item = char>>(iter: Iter) -> usize {
|
||||||
#[inline]
|
|
||||||
fn eq(&self, other: &Self) -> bool {
|
|
||||||
self as *const _ == other as *const _
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn scan_for_terminator(src: &str) -> usize {
|
|
||||||
let mut terminator_idx = 0;
|
let mut terminator_idx = 0;
|
||||||
|
|
||||||
for c in src.chars() {
|
for c in iter {
|
||||||
if c == '\u{0}' {
|
if c == '\u{0}' {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -51,11 +29,82 @@ fn scan_for_terminator(src: &str) -> usize {
|
|||||||
terminator_idx
|
terminator_idx
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct PStrIter {
|
||||||
|
buf: *const u8,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PStrIter {
|
||||||
|
#[inline]
|
||||||
|
fn from(buf: *const u8, idx: usize) -> Self {
|
||||||
|
PStrIter {
|
||||||
|
buf: (buf as usize + idx) as *const _
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Iterator for PStrIter {
|
||||||
|
type Item = char;
|
||||||
|
|
||||||
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
|
unsafe {
|
||||||
|
let b = ptr::read(self.buf);
|
||||||
|
|
||||||
|
if b == 0u8 {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
let c = ptr::read(self.buf as *const char);
|
||||||
|
self.buf = self.buf.offset(c.len_utf8() as isize);
|
||||||
|
|
||||||
|
Some(c)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct PStrIterBounded {
|
||||||
|
buf: *const u8,
|
||||||
|
end: *const u8,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PStrIterBounded {
|
||||||
|
#[inline]
|
||||||
|
fn from(buf: *const u8, start: usize, end: usize) -> Self {
|
||||||
|
PStrIterBounded {
|
||||||
|
buf: (buf as usize + start) as *const _,
|
||||||
|
end: (buf as usize + end) as *const _,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Iterator for PStrIterBounded {
|
||||||
|
type Item = char;
|
||||||
|
|
||||||
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
|
unsafe {
|
||||||
|
if self.buf >= self.end {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
let b = ptr::read(self.buf);
|
||||||
|
|
||||||
|
if b == 0u8 {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
let c = ptr::read(self.buf as *const char);
|
||||||
|
self.buf = self.buf.offset(c.len_utf8() as isize);
|
||||||
|
|
||||||
|
Some(c)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl PartialString {
|
impl PartialString {
|
||||||
|
#[inline]
|
||||||
pub(super)
|
pub(super)
|
||||||
fn new(src: &str) -> Option<(Self, &str)> {
|
fn new(src: &str) -> Option<(Self, &str)> {
|
||||||
let pstr = PartialString {
|
let pstr = PartialString {
|
||||||
buf: RawBlock::with_capacity(src.len() + '\u{0}'.len_utf8()),
|
buf: ptr::null_mut(),
|
||||||
};
|
};
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
@@ -63,22 +112,34 @@ impl PartialString {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub(super)
|
||||||
|
fn empty() -> Self {
|
||||||
|
PartialString {
|
||||||
|
buf: "\u{0}".as_bytes()[0] as *const _,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
unsafe fn append_chars(mut self, src: &str) -> Option<(Self, &str)> {
|
unsafe fn append_chars(mut self, src: &str) -> Option<(Self, &str)> {
|
||||||
let terminator_idx = scan_for_terminator(src);
|
let terminator_idx = scan_for_terminator(src.chars());
|
||||||
|
|
||||||
if terminator_idx == 0 {
|
if terminator_idx == 0 {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
let new_top = self.buf.new_block(terminator_idx + '\u{0}'.len_utf8());
|
let layout = alloc::Layout::from_size_align_unchecked(
|
||||||
|
src.len() + '\u{0}'.len_utf8(),
|
||||||
|
mem::align_of::<u8>(),
|
||||||
|
);
|
||||||
|
|
||||||
|
self.buf = alloc::alloc(layout) as *const _;
|
||||||
|
|
||||||
ptr::copy(
|
ptr::copy(
|
||||||
src.as_ptr(),
|
src.as_ptr(),
|
||||||
self.buf.top as *mut _,
|
self.buf as *mut _,
|
||||||
terminator_idx,
|
terminator_idx,
|
||||||
);
|
);
|
||||||
|
|
||||||
self.buf.top = (new_top as usize - '\u{0}'.len_utf8()) as *const _;
|
|
||||||
self.write_terminator_at(terminator_idx);
|
self.write_terminator_at(terminator_idx);
|
||||||
|
|
||||||
Some(if terminator_idx != src.len() {
|
Some(if terminator_idx != src.len() {
|
||||||
@@ -88,26 +149,40 @@ impl PartialString {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub(crate)
|
||||||
|
fn iter(&self) -> PStrIter {
|
||||||
|
PStrIter {
|
||||||
|
buf: self.buf,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub(super)
|
pub(super)
|
||||||
fn clone_from_offset(&self, n: usize) -> Self {
|
fn clone_from_offset(&self, n: usize) -> Self {
|
||||||
let mut pstr = PartialString {
|
let mut pstr = PartialString {
|
||||||
buf: RawBlock::with_capacity(self.len() + '\u{0}'.len_utf8()),
|
buf: ptr::null_mut(),
|
||||||
};
|
};
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
let len = if self.len() > n { self.len() - n } else { 0 };
|
let len = scan_for_terminator(self.range_from(0 ..));
|
||||||
let new_top = pstr.buf.new_block(len + '\u{0}'.len_utf8());
|
let len = if len > n { len - n } else { 0 };
|
||||||
|
|
||||||
|
let layout = alloc::Layout::from_size_align_unchecked(
|
||||||
|
len + '\u{0}'.len_utf8(),
|
||||||
|
mem::align_of::<u8>(),
|
||||||
|
);
|
||||||
|
|
||||||
|
pstr.buf = alloc::alloc(layout);
|
||||||
|
|
||||||
if len > 0 {
|
if len > 0 {
|
||||||
ptr::copy(
|
ptr::copy(
|
||||||
(self.buf.base as usize + n) as *mut u8,
|
(self.buf as usize + n) as *const u8,
|
||||||
pstr.buf.base as *mut _,
|
pstr.buf as *mut _,
|
||||||
len,
|
len,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
pstr.write_terminator_at(len);
|
pstr.write_terminator_at(len);
|
||||||
pstr.buf.top = (new_top as usize - '\u{0}'.len_utf8()) as *const _;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pstr
|
pstr
|
||||||
@@ -118,23 +193,26 @@ impl PartialString {
|
|||||||
fn write_terminator_at(&mut self, index: usize) {
|
fn write_terminator_at(&mut self, index: usize) {
|
||||||
unsafe {
|
unsafe {
|
||||||
ptr::write(
|
ptr::write(
|
||||||
(self.buf.base as usize + index) as *mut u8,
|
(self.buf as usize + index) as *mut u8,
|
||||||
0u8,
|
0u8,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub(crate)
|
pub fn range(&self, index: Range<usize>) -> PStrIterBounded {
|
||||||
fn block_as_str(&self) -> &str {
|
PStrIterBounded::from(self.buf, index.start, index.end)
|
||||||
unsafe {
|
|
||||||
let slice = slice::from_raw_parts(self.buf.base, self.len());
|
|
||||||
str::from_utf8(slice).unwrap()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn len(&self) -> usize {
|
pub fn range_from(&self, index: RangeFrom<usize>) -> PStrIter {
|
||||||
self.buf.top as usize - self.buf.base as usize
|
PStrIter::from(self.buf, index.start)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn at_end(&self, end_n: usize) -> bool {
|
||||||
|
unsafe {
|
||||||
|
ptr::read((self.buf as usize + end_n) as *const u8) == 0u8
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,7 +29,8 @@ pub enum EOFAction {
|
|||||||
pub enum StreamInstance {
|
pub enum StreamInstance {
|
||||||
Bytes(Cursor<Vec<u8>>),
|
Bytes(Cursor<Vec<u8>>),
|
||||||
DynReadSource(Box<dyn Read>),
|
DynReadSource(Box<dyn Read>),
|
||||||
File(File),
|
File(File),
|
||||||
|
Null,
|
||||||
ReadlineStream(ReadlineStream),
|
ReadlineStream(ReadlineStream),
|
||||||
Stdin,
|
Stdin,
|
||||||
Stdout,
|
Stdout,
|
||||||
@@ -201,6 +202,17 @@ impl Stream {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub(crate)
|
||||||
|
fn null_stream() -> Self {
|
||||||
|
Stream {
|
||||||
|
options: StreamOptions::default(), // TODO: null_options?
|
||||||
|
stream_inst: WrappedStreamInstance::new(
|
||||||
|
StreamInstance::Null
|
||||||
|
),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub(crate)
|
pub(crate)
|
||||||
fn is_stdout(&self) -> bool {
|
fn is_stdout(&self) -> bool {
|
||||||
@@ -233,7 +245,7 @@ impl Stream {
|
|||||||
match *self.stream_inst.0.borrow() {
|
match *self.stream_inst.0.borrow() {
|
||||||
StreamInstance::Stdin
|
StreamInstance::Stdin
|
||||||
| StreamInstance::TcpStream(_)
|
| StreamInstance::TcpStream(_)
|
||||||
| StreamInstance::Bytes(_)
|
| StreamInstance::Bytes(_)
|
||||||
| StreamInstance::ReadlineStream(_)
|
| StreamInstance::ReadlineStream(_)
|
||||||
| StreamInstance::DynReadSource(_)
|
| StreamInstance::DynReadSource(_)
|
||||||
| StreamInstance::File(_) => {
|
| StreamInstance::File(_) => {
|
||||||
@@ -251,7 +263,7 @@ impl Stream {
|
|||||||
match *self.stream_inst.0.borrow() {
|
match *self.stream_inst.0.borrow() {
|
||||||
StreamInstance::Stdout
|
StreamInstance::Stdout
|
||||||
| StreamInstance::TcpStream(_)
|
| StreamInstance::TcpStream(_)
|
||||||
| StreamInstance::Bytes(_)
|
| StreamInstance::Bytes(_)
|
||||||
| StreamInstance::File(_) => {
|
| StreamInstance::File(_) => {
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
@@ -283,7 +295,7 @@ impl Read for Stream {
|
|||||||
StreamInstance::Stdin => {
|
StreamInstance::Stdin => {
|
||||||
stdin().read(buf)
|
stdin().read(buf)
|
||||||
}
|
}
|
||||||
StreamInstance::Stdout => {
|
StreamInstance::Stdout | StreamInstance::Null => {
|
||||||
Err(std::io::Error::new(
|
Err(std::io::Error::new(
|
||||||
ErrorKind::PermissionDenied,
|
ErrorKind::PermissionDenied,
|
||||||
StreamError::ReadFromOutputStream,
|
StreamError::ReadFromOutputStream,
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -4,52 +4,178 @@ macro_rules! interm {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! heap_str {
|
/* A simple macro to count the arguments in a variadic list
|
||||||
($s:expr) => {
|
* of token trees.
|
||||||
HeapCellValue::Addr(Addr::Str($s))
|
*/
|
||||||
};
|
macro_rules! count_tt {
|
||||||
}
|
() => { 0 };
|
||||||
|
($odd:tt $($a:tt $b:tt)*) => { (count_tt!($($a)*) << 1) | 1 };
|
||||||
macro_rules! heap_integer {
|
($($a:tt $even:tt)*) => { count_tt!($($a)*) << 1 };
|
||||||
($i:expr) => {
|
|
||||||
HeapCellValue::Addr(Addr::Con(Constant::Integer($i)))
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! heap_cell {
|
|
||||||
($i:expr) => {
|
|
||||||
HeapCellValue::Addr(Addr::HeapCell($i))
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! heap_con {
|
|
||||||
($i:expr) => {
|
|
||||||
HeapCellValue::Addr(Addr::Con($i))
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! heap_atom {
|
|
||||||
($name:expr) => {
|
|
||||||
HeapCellValue::Addr(Addr::Con(atom!($name)))
|
|
||||||
};
|
|
||||||
($name:expr, $tbl:expr) => {
|
|
||||||
HeapCellValue::Addr(Addr::Con(atom!($name, $tbl)))
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! functor {
|
macro_rules! functor {
|
||||||
|
($name:expr, $fixity:expr, [$($dt:ident($($value:expr),*)),+], [$($aux:ident),*]) => ({
|
||||||
|
{
|
||||||
|
#[allow(unused_variables, unused_mut)]
|
||||||
|
let mut addendum = Heap::new();
|
||||||
|
let arity = count_tt!($($dt) +);
|
||||||
|
let aux_lens = [$($aux.len()),*];
|
||||||
|
|
||||||
|
let mut result =
|
||||||
|
vec![ HeapCellValue::NamedStr(arity, clause_name!($name), Some($fixity)),
|
||||||
|
$(functor_term!( $dt($($value),*), arity, aux_lens, addendum ),)+ ];
|
||||||
|
|
||||||
|
$(
|
||||||
|
result.extend($aux.into_iter());
|
||||||
|
)*
|
||||||
|
|
||||||
|
result.extend(addendum.into_iter());
|
||||||
|
result
|
||||||
|
}
|
||||||
|
});
|
||||||
|
($name:expr, $fixity:expr, [$($dt:ident($($value:expr),*)),+]) => ({
|
||||||
|
{
|
||||||
|
#[allow(unused_variables, unused_mut)]
|
||||||
|
let mut addendum = Heap::new();
|
||||||
|
let arity = count_tt!($($dt) +);
|
||||||
|
|
||||||
|
let mut result =
|
||||||
|
vec![ HeapCellValue::NamedStr(arity, clause_name!($name), Some($fixity)),
|
||||||
|
$(functor_term!( $dt($($value),*), arity, [], addendum ),)+ ];
|
||||||
|
|
||||||
|
result.extend(addendum.into_iter());
|
||||||
|
result
|
||||||
|
}
|
||||||
|
});
|
||||||
|
($name:expr, [$($dt:ident($($value:expr),*)),+], [$($aux:ident),*]) => ({
|
||||||
|
{
|
||||||
|
#[allow(unused_variables, unused_mut)]
|
||||||
|
let mut addendum = Heap::new();
|
||||||
|
let arity = count_tt!($($dt) +);
|
||||||
|
let aux_lens = [$($aux.len()),*];
|
||||||
|
|
||||||
|
let mut result =
|
||||||
|
vec![ HeapCellValue::NamedStr(arity, clause_name!($name), None),
|
||||||
|
$(functor_term!( $dt($($value),*), arity, aux_lens, addendum ),)+ ];
|
||||||
|
|
||||||
|
$(
|
||||||
|
result.extend($aux.into_iter());
|
||||||
|
)*
|
||||||
|
|
||||||
|
result.extend(addendum.into_iter());
|
||||||
|
result
|
||||||
|
}
|
||||||
|
});
|
||||||
|
($name:expr, [$($dt:ident($($value:expr),*)),+]) => ({
|
||||||
|
{
|
||||||
|
let arity = count_tt!($($dt) +);
|
||||||
|
|
||||||
|
vec![ HeapCellValue::NamedStr(arity, clause_name!($name), None),
|
||||||
|
$(functor_term!( $dt($($value),*), arity, [], addendum ),)+ ]
|
||||||
|
}
|
||||||
|
});
|
||||||
|
($name:expr, $fixity:expr) => (
|
||||||
|
vec![ HeapCellValue::Atom(clause_name!($name), Some($fixity)) ]
|
||||||
|
);
|
||||||
|
(clause_name($name:expr)) => (
|
||||||
|
vec![ HeapCellValue::Atom($name, None) ]
|
||||||
|
);
|
||||||
($name:expr) => (
|
($name:expr) => (
|
||||||
vec![ heap_atom!($name) ]
|
vec![ HeapCellValue::Atom(clause_name!($name), None) ]
|
||||||
);
|
);
|
||||||
($name:expr, $len:expr) => (
|
}
|
||||||
vec![ HeapCellValue::NamedStr($len, clause_name!($name), None) ]
|
|
||||||
|
macro_rules! functor_term {
|
||||||
|
(aux(0), $arity:expr, $aux_lens:expr, $addendum:ident) => ({
|
||||||
|
HeapCellValue::Addr(Addr::HeapCell($arity + 1))
|
||||||
|
});
|
||||||
|
(aux($e:expr), $arity:expr, $aux_lens:expr, $addendum:ident) => ({
|
||||||
|
let len: usize = $aux_lens[0 .. $e].iter().sum();
|
||||||
|
HeapCellValue::Addr(Addr::HeapCell($arity + 1 + len))
|
||||||
|
});
|
||||||
|
(aux($h:expr, 0), $arity:expr, $aux_lens:expr, $addendum:ident) => ({
|
||||||
|
HeapCellValue::Addr(Addr::HeapCell($arity + $h + 1))
|
||||||
|
});
|
||||||
|
(aux($h:expr, $e:expr), $arity:expr, $aux_lens:expr, $addendum:ident) => ({
|
||||||
|
let len: usize = $aux_lens[0 .. $e].iter().sum();
|
||||||
|
HeapCellValue::Addr(Addr::HeapCell($arity + $h + 1 + len))
|
||||||
|
});
|
||||||
|
(addr($e:expr), $arity:expr, $aux_lens:expr, $addendum:ident) => (
|
||||||
|
HeapCellValue::Addr($e)
|
||||||
);
|
);
|
||||||
($name:expr, $len:expr, [$($args:expr),*]) => (
|
(constant($h:expr, $e:expr), $arity:expr, $aux_lens:expr, $addendum:ident) => (
|
||||||
vec![ HeapCellValue::NamedStr($len, clause_name!($name), None), $($args),* ]
|
from_constant!($e, $h, $arity, $aux_lens, $addendum)
|
||||||
|
);
|
||||||
|
(constant($e:expr), $arity:expr, $aux_lens:expr, $addendum:ident) => (
|
||||||
|
from_constant!($e, 0, $arity, $aux_lens, $addendum)
|
||||||
);
|
);
|
||||||
($name:expr, $len:expr, [$($args:expr),*], $fix: expr) => (
|
(number($e:expr), $arity:expr, $aux_lens:expr, $addendum:ident) => (
|
||||||
vec![ HeapCellValue::NamedStr($len, clause_name!($name), Some($fix)), $($args),* ]
|
$e.into()
|
||||||
);
|
);
|
||||||
|
/*
|
||||||
|
(string($s:expr), $arity:expr, $aux_lens:expr, $addendum: ident) => ({
|
||||||
|
let len: usize = $aux_lens.iter().sum();
|
||||||
|
let h = len + $arity + 1 + $addendum.h();
|
||||||
|
|
||||||
|
$addendum.allocate_pstr(&$s);
|
||||||
|
|
||||||
|
HeapCell::PStrLocation(h, 0)
|
||||||
|
});
|
||||||
|
*/
|
||||||
|
(integer($e:expr), $arity:expr, $aux_lens:expr, $addendum: ident) => (
|
||||||
|
HeapCellValue::Integer(Rc::new(Integer::from($e)))
|
||||||
|
);
|
||||||
|
(clause_name($e:expr), $arity:expr, $aux_lens:expr, $addendum: ident) => (
|
||||||
|
HeapCellValue::Atom($e, None)
|
||||||
|
);
|
||||||
|
(atom($e:expr), $arity:expr, $aux_lens:expr, $addendum: ident) => (
|
||||||
|
HeapCellValue::Atom(clause_name!($e), None)
|
||||||
|
);
|
||||||
|
($e:expr, $arity:expr, $aux_lens:expr, $addendum:ident) => (
|
||||||
|
$e
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! from_constant {
|
||||||
|
($e:expr, $over_h:expr, $arity:expr, $aux_lens:expr, $addendum:ident) => ({
|
||||||
|
match $e {
|
||||||
|
&Constant::Atom(ref name, ref op) => {
|
||||||
|
HeapCellValue::Atom(name.clone(), op.clone())
|
||||||
|
}
|
||||||
|
&Constant::Char(c) => {
|
||||||
|
HeapCellValue::Addr(Addr::Char(c))
|
||||||
|
}
|
||||||
|
&Constant::CharCode(c) => {
|
||||||
|
HeapCellValue::Addr(Addr::CharCode(c))
|
||||||
|
}
|
||||||
|
&Constant::CutPoint(cp) => {
|
||||||
|
HeapCellValue::Addr(Addr::CutPoint(cp))
|
||||||
|
}
|
||||||
|
&Constant::Integer(ref n) => {
|
||||||
|
HeapCellValue::Integer(n.clone())
|
||||||
|
}
|
||||||
|
&Constant::Rational(ref r) => {
|
||||||
|
HeapCellValue::Rational(r.clone())
|
||||||
|
}
|
||||||
|
&Constant::Float(f) => {
|
||||||
|
HeapCellValue::Addr(Addr::Float(f))
|
||||||
|
}
|
||||||
|
&Constant::String(ref s) => {
|
||||||
|
let len: usize = $aux_lens.iter().sum();
|
||||||
|
let h = len + $arity + 1 + $addendum.h() + $over_h;
|
||||||
|
|
||||||
|
$addendum.put_constant(Constant::String(s.clone()));
|
||||||
|
|
||||||
|
HeapCellValue::Addr(Addr::PStrLocation(h, 0))
|
||||||
|
}
|
||||||
|
&Constant::Usize(u) => {
|
||||||
|
HeapCellValue::Addr(Addr::Usize(u))
|
||||||
|
}
|
||||||
|
&Constant::EmptyList => {
|
||||||
|
HeapCellValue::Addr(Addr::EmptyList)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! is_atom {
|
macro_rules! is_atom {
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ use prolog_parser::tabled_rc::TabledData;
|
|||||||
|
|
||||||
use crate::prolog::forms::*;
|
use crate::prolog::forms::*;
|
||||||
use crate::prolog::iterators::*;
|
use crate::prolog::iterators::*;
|
||||||
|
use crate::prolog::machine::heap::Heap;
|
||||||
use crate::prolog::machine::machine_indices::*;
|
use crate::prolog::machine::machine_indices::*;
|
||||||
use crate::prolog::machine::machine_state::MachineState;
|
use crate::prolog::machine::machine_state::MachineState;
|
||||||
use crate::prolog::machine::streams::Stream;
|
use crate::prolog::machine::streams::Stream;
|
||||||
@@ -13,12 +14,20 @@ use std::collections::VecDeque;
|
|||||||
type SubtermDeque = VecDeque<(usize, usize)>;
|
type SubtermDeque = VecDeque<(usize, usize)>;
|
||||||
|
|
||||||
impl<'a> TermRef<'a> {
|
impl<'a> TermRef<'a> {
|
||||||
fn as_addr(&self, h: usize) -> Addr {
|
fn as_addr(&self, heap: &mut Heap, h: usize) -> Addr {
|
||||||
match self {
|
match self {
|
||||||
&TermRef::AnonVar(_) | &TermRef::Var(..) => Addr::HeapCell(h),
|
&TermRef::AnonVar(_) | &TermRef::Var(..) => {
|
||||||
&TermRef::Cons(..) => Addr::HeapCell(h),
|
Addr::HeapCell(h)
|
||||||
&TermRef::Constant(_, _, c) => Addr::Con(c.clone()),
|
}
|
||||||
&TermRef::Clause(..) => Addr::Str(h),
|
&TermRef::Cons(..) => {
|
||||||
|
Addr::HeapCell(h)
|
||||||
|
}
|
||||||
|
&TermRef::Constant(_, _, c) => {
|
||||||
|
heap.put_constant(c.clone())
|
||||||
|
}
|
||||||
|
&TermRef::Clause(..) => {
|
||||||
|
Addr::Str(h)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -131,7 +140,7 @@ fn modify_head_of_queue(
|
|||||||
h: usize,
|
h: usize,
|
||||||
) {
|
) {
|
||||||
if let Some((arity, site_h)) = queue.pop_front() {
|
if let Some((arity, site_h)) = queue.pop_front() {
|
||||||
machine_st.heap[site_h] = HeapCellValue::Addr(term.as_addr(h));
|
machine_st.heap[site_h] = HeapCellValue::Addr(term.as_addr(&mut machine_st.heap, h));
|
||||||
|
|
||||||
if arity > 1 {
|
if arity > 1 {
|
||||||
queue.push_front((arity - 1, site_h + 1));
|
queue.push_front((arity - 1, site_h + 1));
|
||||||
@@ -180,10 +189,12 @@ pub(crate) fn write_term_to_heap(term: &Term, machine_st: &mut MachineState) ->
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
&TermRef::AnonVar(Level::Root) | &TermRef::Constant(Level::Root, ..) => {
|
&TermRef::AnonVar(Level::Root) | &TermRef::Constant(Level::Root, ..) => {
|
||||||
machine_st.heap.push(HeapCellValue::Addr(term.as_addr(h)))
|
let value = HeapCellValue::Addr(term.as_addr(&mut machine_st.heap, h));
|
||||||
|
machine_st.heap.push(value);
|
||||||
}
|
}
|
||||||
&TermRef::Var(Level::Root, ..) => {
|
&TermRef::Var(Level::Root, ..) => {
|
||||||
machine_st.heap.push(HeapCellValue::Addr(term.as_addr(h)))
|
let value = HeapCellValue::Addr(term.as_addr(&mut machine_st.heap, h));
|
||||||
|
machine_st.heap.push(value);
|
||||||
}
|
}
|
||||||
&TermRef::AnonVar(_) => {
|
&TermRef::AnonVar(_) => {
|
||||||
if let Some((arity, site_h)) = queue.pop_front() {
|
if let Some((arity, site_h)) = queue.pop_front() {
|
||||||
|
|||||||
@@ -43,6 +43,7 @@
|
|||||||
).
|
).
|
||||||
|
|
||||||
'$submit_query_and_print_results'(Term0, VarList) :-
|
'$submit_query_and_print_results'(Term0, VarList) :-
|
||||||
|
write('oh brother'), nl,
|
||||||
( expand_goals(Term0, Term) -> true
|
( expand_goals(Term0, Term) -> true
|
||||||
; Term0 = Term
|
; Term0 = Term
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -143,6 +143,10 @@ impl fmt::Display for HeapCellValue {
|
|||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
&HeapCellValue::Addr(ref addr) => write!(f, "{}", addr),
|
&HeapCellValue::Addr(ref addr) => write!(f, "{}", addr),
|
||||||
|
&HeapCellValue::Atom(ref atom, _) => write!(f, "{}", atom.as_str()),
|
||||||
|
&HeapCellValue::DBRef(ref db_ref) => write!(f, "{}", db_ref),
|
||||||
|
&HeapCellValue::Integer(ref n) => write!(f, "{}", n),
|
||||||
|
&HeapCellValue::Rational(ref n) => write!(f, "{}", n),
|
||||||
&HeapCellValue::NamedStr(arity, ref name, Some(ref cell)) => write!(
|
&HeapCellValue::NamedStr(arity, ref name, Some(ref cell)) => write!(
|
||||||
f,
|
f,
|
||||||
"{}/{} (op, priority: {}, spec: {})",
|
"{}/{} (op, priority: {}, spec: {})",
|
||||||
@@ -155,7 +159,10 @@ impl fmt::Display for HeapCellValue {
|
|||||||
write!(f, "{}/{}", name.as_str(), arity)
|
write!(f, "{}/{}", name.as_str(), arity)
|
||||||
}
|
}
|
||||||
&HeapCellValue::PartialString(ref pstr) => {
|
&HeapCellValue::PartialString(ref pstr) => {
|
||||||
write!(f, "pstr ( buf: {} )", pstr.block_as_str())
|
write!(f, "pstr ( buf: 0x{:x} )", (pstr as *const _) as usize)
|
||||||
|
}
|
||||||
|
&HeapCellValue::Stream(ref stream) => {
|
||||||
|
write!(f, "$stream({})", stream.as_ptr() as usize)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -175,15 +182,20 @@ impl fmt::Display for DBRef {
|
|||||||
impl fmt::Display for Addr {
|
impl fmt::Display for Addr {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
|
&Addr::Char(c) => write!(f, "Addr::Char({})", c),
|
||||||
|
&Addr::CharCode(c) => write!(f, "Addr::CharCode({})", c),
|
||||||
|
&Addr::EmptyList => write!(f, "Addr::EmptyList"),
|
||||||
|
&Addr::Float(fl) => write!(f, "Addr::Float({})", fl),
|
||||||
|
&Addr::CutPoint(cp) => write!(f, "Addr::CutPoint({})", cp),
|
||||||
&Addr::Con(ref c) => write!(f, "Addr::Con({})", c),
|
&Addr::Con(ref c) => write!(f, "Addr::Con({})", c),
|
||||||
&Addr::DBRef(ref db_ref) => write!(f, "Addr::DBRef({})", db_ref),
|
|
||||||
&Addr::Lis(l) => write!(f, "Addr::Lis({})", l),
|
&Addr::Lis(l) => write!(f, "Addr::Lis({})", l),
|
||||||
&Addr::AttrVar(h) => write!(f, "Addr::AttrVar({})", h),
|
&Addr::AttrVar(h) => write!(f, "Addr::AttrVar({})", h),
|
||||||
&Addr::HeapCell(h) => write!(f, "Addr::HeapCell({})", h),
|
&Addr::HeapCell(h) => write!(f, "Addr::HeapCell({})", h),
|
||||||
&Addr::StackCell(fr, sc) => write!(f, "Addr::StackCell({}, {})", fr, sc),
|
&Addr::StackCell(fr, sc) => write!(f, "Addr::StackCell({}, {})", fr, sc),
|
||||||
&Addr::Str(s) => write!(f, "Addr::Str({})", s),
|
&Addr::Str(s) => write!(f, "Addr::Str({})", s),
|
||||||
&Addr::PStrLocation(h, n) => write!(f, "Addr::PStrLocation({}, {})", h, n),
|
&Addr::PStrLocation(h, n) => write!(f, "Addr::PStrLocation({}, {})", h, n),
|
||||||
&Addr::Stream(ref stream) => write!(f, "Addr::Stream({})", stream.as_ptr() as usize),
|
&Addr::Stream(stream) => write!(f, "Addr::Stream({})", stream),
|
||||||
|
&Addr::Usize(cp) => write!(f, "Addr::Usize({})", cp),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user