use fixnums in place of bignums where possible

This commit is contained in:
Mark Thom
2020-04-05 20:32:16 -06:00
parent c8855f97e8
commit d76ae413c4
26 changed files with 1915 additions and 1195 deletions

6
Cargo.lock generated
View File

@@ -444,7 +444,7 @@ dependencies = [
[[package]] [[package]]
name = "prolog_parser" name = "prolog_parser"
version = "0.8.48" version = "0.8.49"
source = "registry+https://github.com/rust-lang/crates.io-index" 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)",
@@ -580,7 +580,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.48 (registry+https://github.com/rust-lang/crates.io-index)", "prolog_parser 0.8.49 (registry+https://github.com/rust-lang/crates.io-index)",
"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 +791,7 @@ 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.48 (registry+https://github.com/rust-lang/crates.io-index)" = "301d67e5905691f8d5dc5f08c8c6e12cf849a12bea779af8b5221c35b89faf95" "checksum prolog_parser 0.8.49 (registry+https://github.com/rust-lang/crates.io-index)" = "82f46113e58039861f82f6b6cdaca94c0997eda2c7317a4c4f13d549c4601eec"
"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"

View File

@@ -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.48", default-features = false } prolog_parser = { version = "0.8.49", 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"

View File

@@ -6,6 +6,7 @@ use crate::prolog::forms::*;
use crate::prolog::instructions::*; use crate::prolog::instructions::*;
use crate::prolog::iterators::*; use crate::prolog::iterators::*;
use crate::prolog::machine::heap::*;
use crate::prolog::machine::machine_errors::*; use crate::prolog::machine::machine_errors::*;
use crate::prolog::machine::machine_indices::*; use crate::prolog::machine::machine_indices::*;
@@ -15,6 +16,7 @@ use crate::prolog::rug::{Assign, Integer, Rational};
use std::cell::Cell; use std::cell::Cell;
use std::cmp::{max, min, Ordering}; use std::cmp::{max, min, Ordering};
use std::convert::TryFrom;
use std::f64; use std::f64;
use std::num::FpCategory; use std::num::FpCategory;
use std::ops::{Add, Div, Mul, Neg, Sub}; use std::ops::{Add, Div, Mul, Neg, Sub};
@@ -262,6 +264,9 @@ impl<'a> ArithmeticEvaluator<'a> {
fn push_constant(&mut self, c: &Constant) -> Result<(), ArithmeticError> { fn push_constant(&mut self, c: &Constant) -> Result<(), ArithmeticError> {
match c { match c {
&Constant::Fixnum(n) => self
.interm
.push(ArithmeticTerm::Number(Number::Fixnum(n))),
&Constant::Integer(ref n) => self &Constant::Integer(ref n) => self
.interm .interm
.push(ArithmeticTerm::Number(Number::Integer(n.clone()))), .push(ArithmeticTerm::Number(Number::Integer(n.clone()))),
@@ -316,18 +321,25 @@ impl<'a> ArithmeticEvaluator<'a> {
} }
// integer division rounding function -- 9.1.3.1. // integer division rounding function -- 9.1.3.1.
pub fn rnd_i<'a>(n: &'a Number) -> RefOrOwned<'a, Integer> { pub fn rnd_i<'a>(n: &'a Number) -> RefOrOwned<'a, Number> {
match n { match n {
&Number::Integer(ref n) => RefOrOwned::Borrowed(n), &Number::Integer(_) => {
RefOrOwned::Borrowed(n)
}
&Number::Float(OrderedFloat(f)) => { &Number::Float(OrderedFloat(f)) => {
RefOrOwned::Owned(Integer::from_f64(f.floor()).unwrap_or_else(|| Integer::from(0))) RefOrOwned::Owned(Number::from(
Integer::from_f64(f.floor()).unwrap_or_else(|| Integer::from(0))
))
}
&Number::Fixnum(n) => {
RefOrOwned::Owned(Number::from(n))
} }
&Number::Rational(ref r) => { &Number::Rational(ref r) => {
let r_ref = r.fract_floor_ref(); let r_ref = r.fract_floor_ref();
let (mut fract, mut floor) = (Rational::new(), Integer::new()); let (mut fract, mut floor) = (Rational::new(), Integer::new());
(&mut fract, &mut floor).assign(r_ref); (&mut fract, &mut floor).assign(r_ref);
RefOrOwned::Owned(floor)
RefOrOwned::Owned(Number::from(floor))
} }
} }
} }
@@ -335,6 +347,7 @@ pub fn rnd_i<'a>(n: &'a Number) -> RefOrOwned<'a, Integer> {
// floating point rounding function -- 9.1.4.1. // floating point rounding function -- 9.1.4.1.
pub fn rnd_f(n: &Number) -> f64 { pub fn rnd_f(n: &Number) -> f64 {
match n { match n {
&Number::Fixnum(n) => n as f64,
&Number::Integer(ref n) => n.to_f64(), &Number::Integer(ref n) => n.to_f64(),
&Number::Float(OrderedFloat(f)) => f, &Number::Float(OrderedFloat(f)) => f,
&Number::Rational(ref r) => r.to_f64(), &Number::Rational(ref r) => r.to_f64(),
@@ -370,22 +383,32 @@ where
} }
} }
#[inline]
fn float_fn_to_f(n: isize) -> Result<f64, EvalError> {
classify_float(n as f64, rnd_f)
}
#[inline]
fn float_i_to_f(n: &Integer) -> Result<f64, EvalError> { fn float_i_to_f(n: &Integer) -> Result<f64, EvalError> {
classify_float(n.to_f64(), rnd_f) classify_float(n.to_f64(), rnd_f)
} }
#[inline]
fn float_r_to_f(r: &Rational) -> Result<f64, EvalError> { fn float_r_to_f(r: &Rational) -> Result<f64, EvalError> {
classify_float(r.to_f64(), rnd_f) classify_float(r.to_f64(), rnd_f)
} }
#[inline]
fn add_f(f1: f64, f2: f64) -> Result<OrderedFloat<f64>, EvalError> { fn add_f(f1: f64, f2: f64) -> Result<OrderedFloat<f64>, EvalError> {
Ok(OrderedFloat(classify_float(f1 + f2, rnd_f)?)) Ok(OrderedFloat(classify_float(f1 + f2, rnd_f)?))
} }
#[inline]
fn mul_f(f1: f64, f2: f64) -> Result<OrderedFloat<f64>, EvalError> { fn mul_f(f1: f64, f2: f64) -> Result<OrderedFloat<f64>, EvalError> {
Ok(OrderedFloat(classify_float(f1 * f2, rnd_f)?)) Ok(OrderedFloat(classify_float(f1 * f2, rnd_f)?))
} }
#[inline]
fn div_f(f1: f64, f2: f64) -> Result<OrderedFloat<f64>, EvalError> { fn div_f(f1: f64, f2: f64) -> Result<OrderedFloat<f64>, EvalError> {
if FpCategory::Zero == f2.classify() { if FpCategory::Zero == f2.classify() {
Err(EvalError::ZeroDivisor) Err(EvalError::ZeroDivisor)
@@ -399,8 +422,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::Fixnum(n1), Number::Fixnum(n2)) => {
Ok(if let Some(result) = n1.checked_add(n2) {
Number::Fixnum(result)
} else {
Number::from(Integer::from(n1) + Integer::from(n2))
})
}
(Number::Fixnum(n1), Number::Integer(n2)) |
(Number::Integer(n2), Number::Fixnum(n1)) => {
Ok(Number::from(Integer::from(n1) + &*n2))
}
(Number::Fixnum(n1), Number::Rational(n2)) |
(Number::Rational(n2), Number::Fixnum(n1)) => {
Ok(Number::from(Rational::from(n1) + &*n2))
}
(Number::Fixnum(n1), Number::Float(OrderedFloat(n2))) |
(Number::Float(OrderedFloat(n2)), Number::Fixnum(n1)) => {
Ok(Number::Float(add_f(float_fn_to_f(n1)?, n2)?))
}
(Number::Integer(n1), Number::Integer(n2)) => { (Number::Integer(n1), Number::Integer(n2)) => {
Ok(Number::Integer(Rc::new(Integer::from(&*n1) + &*n2))) // add_i Ok(Number::from(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)) => {
@@ -408,7 +450,7 @@ impl Add<Number> for Number {
} }
(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(Rc::new(Rational::from(&*n1) + &*n2))) Ok(Number::from(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)) => {
@@ -418,7 +460,7 @@ impl Add<Number> for Number {
Ok(Number::Float(add_f(f1, f2)?)) Ok(Number::Float(add_f(f1, f2)?))
} }
(Number::Rational(r1), Number::Rational(r2)) => { (Number::Rational(r1), Number::Rational(r2)) => {
Ok(Number::Rational(Rc::new(Rational::from(&*r1) + &*r2))) Ok(Number::from(Rational::from(&*r1) + &*r2))
} }
} }
} }
@@ -429,6 +471,7 @@ impl Neg for Number {
fn neg(self) -> Self::Output { fn neg(self) -> Self::Output {
match self { match self {
Number::Fixnum(n) => Number::Fixnum(-n),
Number::Integer(n) => Number::Integer(Rc::new(-Integer::from(&*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(Rc::new(-Rational::from(&*r))), Number::Rational(r) => Number::Rational(Rc::new(-Rational::from(&*r))),
@@ -449,6 +492,25 @@ 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::Fixnum(n1), Number::Fixnum(n2)) => {
Ok(if let Some(result) = n1.checked_mul(n2) {
Number::Fixnum(result)
} else {
Number::from(Integer::from(n1) * Integer::from(n2))
})
}
(Number::Fixnum(n1), Number::Integer(n2)) |
(Number::Integer(n2), Number::Fixnum(n1)) => {
Ok(Number::from(Integer::from(n1) * &*n2))
}
(Number::Fixnum(n1), Number::Rational(n2)) |
(Number::Rational(n2), Number::Fixnum(n1)) => {
Ok(Number::from(Rational::from(n1) * &*n2))
}
(Number::Fixnum(n1), Number::Float(OrderedFloat(n2))) |
(Number::Float(OrderedFloat(n2)), Number::Fixnum(n1)) => {
Ok(Number::Float(mul_f(float_fn_to_f(n1)?, n2)?))
}
(Number::Integer(n1), Number::Integer(n2)) => { (Number::Integer(n1), Number::Integer(n2)) => {
Ok(Number::Integer(Rc::new(Integer::from(&*n1) * &*n2))) // mul_i Ok(Number::Integer(Rc::new(Integer::from(&*n1) * &*n2))) // mul_i
} }
@@ -479,24 +541,72 @@ impl Div<Number> for Number {
fn div(self, rhs: Number) -> Self::Output { fn div(self, rhs: Number) -> Self::Output {
match (self, rhs) { match (self, rhs) {
(Number::Integer(n1), Number::Integer(n2)) => Ok(Number::Float(div_f( (Number::Fixnum(n1), Number::Fixnum(n2)) => {
float_i_to_f(&n1)?, Ok(Number::Float(div_f(
float_i_to_f(&n2)?, float_fn_to_f(n1)?,
)?)), float_fn_to_f(n2)?,
)?))
}
(Number::Fixnum(n1), Number::Integer(n2)) => {
Ok(Number::Float(div_f(
float_fn_to_f(n1)?,
float_i_to_f(&n2)?,
)?))
}
(Number::Integer(n1), Number::Fixnum(n2)) => {
Ok(Number::Float(div_f(
float_i_to_f(&n1)?,
float_fn_to_f(n2)?,
)?))
}
(Number::Fixnum(n1), Number::Rational(n2)) => {
Ok(Number::Float(div_f(
float_fn_to_f(n1)?,
float_r_to_f(&n2)?,
)?))
}
(Number::Rational(n1), Number::Fixnum(n2)) => {
Ok(Number::Float(div_f(
float_r_to_f(&n1)?,
float_fn_to_f(n2)?,
)?))
}
(Number::Fixnum(n1), Number::Float(OrderedFloat(n2))) => {
Ok(Number::Float(div_f(
float_fn_to_f(n1)?,
n2,
)?))
}
(Number::Float(OrderedFloat(n1)), Number::Fixnum(n2)) => {
Ok(Number::Float(div_f(
n1,
float_fn_to_f(n2)?,
)?))
}
(Number::Integer(n1), Number::Integer(n2)) => {
Ok(Number::Float(div_f(
float_i_to_f(&n1)?,
float_i_to_f(&n2)?,
)?))
}
(Number::Integer(n1), Number::Float(OrderedFloat(n2))) => { (Number::Integer(n1), Number::Float(OrderedFloat(n2))) => {
Ok(Number::Float(div_f(float_i_to_f(&n1)?, n2)?)) Ok(Number::Float(div_f(float_i_to_f(&n1)?, n2)?))
} }
(Number::Float(OrderedFloat(n2)), Number::Integer(n1)) => { (Number::Float(OrderedFloat(n2)), Number::Integer(n1)) => {
Ok(Number::Float(div_f(n2, float_i_to_f(&n1)?)?)) Ok(Number::Float(div_f(n2, float_i_to_f(&n1)?)?))
} }
(Number::Integer(n1), Number::Rational(n2)) => Ok(Number::Float(div_f( (Number::Integer(n1), Number::Rational(n2)) => {
float_i_to_f(&n1)?, Ok(Number::Float(div_f(
float_r_to_f(&n2)?, float_i_to_f(&n1)?,
)?)), float_r_to_f(&n2)?,
(Number::Rational(n2), Number::Integer(n1)) => Ok(Number::Float(div_f( )?))
float_r_to_f(&n2)?, }
float_i_to_f(&n1)?, (Number::Rational(n2), Number::Integer(n1)) => {
)?)), Ok(Number::Float(div_f(
float_r_to_f(&n2)?,
float_i_to_f(&n1)?,
)?))
}
(Number::Rational(n1), Number::Float(OrderedFloat(n2))) => { (Number::Rational(n1), Number::Float(OrderedFloat(n2))) => {
Ok(Number::Float(div_f(float_r_to_f(&n1)?, n2)?)) Ok(Number::Float(div_f(float_r_to_f(&n1)?, n2)?))
} }
@@ -514,25 +624,47 @@ impl Div<Number> for Number {
} }
} }
impl PartialEq for Number {
fn eq(&self, rhs: &Self) -> bool {
match (self, rhs) {
(&Number::Fixnum(n1), &Number::Fixnum(n2)) => n1.eq(&n2),
(&Number::Fixnum(n1), &Number::Integer(ref n2)) => n1.eq(&**n2),
(&Number::Integer(ref n1), &Number::Fixnum(n2)) => (&**n1).eq(&n2),
(&Number::Fixnum(n1), &Number::Rational(ref n2)) => n1.eq(&**n2),
(&Number::Rational(ref n1), &Number::Fixnum(n2)) => (&**n1).eq(&n2),
(&Number::Fixnum(_), &Number::Float(OrderedFloat(_))) => false,
(&Number::Float(OrderedFloat(_)), &Number::Fixnum(_)) => false,
(&Number::Integer(ref n1), &Number::Integer(ref n2)) => n1.eq(n2),
(&Number::Integer(_), Number::Float(_)) => false,
(&Number::Float(_), &Number::Integer(_)) => false,
(&Number::Integer(_), &Number::Rational(_)) => false,
(&Number::Rational(_), &Number::Integer(_)) => false,
(&Number::Rational(_), Number::Float(_)) => false,
(&Number::Float(_), &Number::Rational(_)) => false,
(&Number::Float(f1), &Number::Float(f2)) => f1.eq(&f2),
(&Number::Rational(ref r1), &Number::Rational(ref r2)) => r1.eq(&r2),
}
}
}
impl Eq for Number {}
impl PartialOrd for Number { impl PartialOrd for Number {
fn partial_cmp(&self, rhs: &Number) -> Option<Ordering> { fn partial_cmp(&self, rhs: &Number) -> Option<Ordering> {
match (self, rhs) { Some(self.cmp(rhs))
(&Number::Integer(ref n1), &Number::Integer(ref n2)) => Some(n1.cmp(n2)),
(&Number::Integer(_), Number::Float(_)) => Some(Ordering::Greater),
(&Number::Float(_), &Number::Integer(_)) => Some(Ordering::Less),
(&Number::Integer(_), &Number::Rational(_)) => Some(Ordering::Greater),
(&Number::Rational(_), &Number::Integer(_)) => Some(Ordering::Less),
(&Number::Rational(_), Number::Float(_)) => Some(Ordering::Greater),
(&Number::Float(_), &Number::Rational(_)) => Some(Ordering::Less),
(&Number::Float(f1), &Number::Float(f2)) => Some(f1.cmp(&f2)),
(&Number::Rational(ref r1), &Number::Rational(ref r2)) => Some(r1.cmp(&r2)),
}
} }
} }
impl Ord for Number { impl Ord for Number {
fn cmp(&self, rhs: &Number) -> Ordering { fn cmp(&self, rhs: &Number) -> Ordering {
match (self, rhs) { match (self, rhs) {
(&Number::Fixnum(n1), &Number::Fixnum(n2)) => n1.cmp(&n2),
(&Number::Fixnum(n1), Number::Integer(n2)) => Integer::from(n1).cmp(&*n2),
(Number::Integer(n1), &Number::Fixnum(n2)) => (&**n1).cmp(&Integer::from(n2)),
(&Number::Fixnum(n1), Number::Rational(n2)) => Rational::from(n1).cmp(&*n2),
(Number::Rational(n1), &Number::Fixnum(n2)) => (&**n1).cmp(&Rational::from(n2)),
(&Number::Fixnum(_), &Number::Float(OrderedFloat(_))) => Ordering::Greater,
(&Number::Float(OrderedFloat(_)), &Number::Fixnum(_)) => Ordering::Less,
(&Number::Integer(ref n1), &Number::Integer(ref n2)) => n1.cmp(n2), (&Number::Integer(ref n1), &Number::Integer(ref n2)) => n1.cmp(n2),
(&Number::Integer(_), Number::Float(_)) => Ordering::Greater, (&Number::Integer(_), Number::Float(_)) => Ordering::Greater,
(&Number::Float(_), &Number::Integer(_)) => Ordering::Less, (&Number::Float(_), &Number::Integer(_)) => Ordering::Less,
@@ -546,6 +678,78 @@ impl Ord for Number {
} }
} }
impl<'a> TryFrom<(Addr, &'a Heap)> for Number {
type Error = ();
fn try_from((addr, heap): (Addr, &'a Heap)) -> Result<Number, Self::Error> {
match addr {
Addr::CharCode(c) => {
Ok(Number::from(c as isize))
}
Addr::Fixnum(n) => {
Ok(Number::from(n))
}
Addr::Float(n) => {
Ok(Number::Float(n))
}
Addr::Usize(n) => {
if let Ok(n) = isize::try_from(n) {
Ok(Number::from(n))
} else {
Ok(Number::from(Integer::from(n)))
}
}
Addr::Con(h) => {
Number::try_from(&heap[h])
}
_ => {
Err(())
}
}
}
}
impl<'a> TryFrom<&'a HeapCellValue> for Number {
type Error = ();
fn try_from(value: &'a HeapCellValue) -> Result<Number, Self::Error> {
match value {
HeapCellValue::Addr(addr) => {
match addr {
&Addr::CharCode(c) => {
Ok(Number::from(c as isize))
}
&Addr::Fixnum(n) => {
Ok(Number::from(n))
}
&Addr::Float(n) => {
Ok(Number::Float(n))
}
&Addr::Usize(n) => {
if let Ok(n) = isize::try_from(n) {
Ok(Number::from(n))
} else {
Ok(Number::from(Integer::from(n)))
}
}
_ => {
Err(())
}
}
}
HeapCellValue::Integer(n) => {
Ok(Number::Integer(n.clone()))
}
HeapCellValue::Rational(n) => {
Ok(Number::Rational(n.clone()))
}
_ => {
Err(())
}
}
}
}
// 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 = Integer::from(power.abs_ref()); let mut power = Integer::from(power.abs_ref());

View File

@@ -159,7 +159,6 @@ pub enum SystemClauseType {
AtomCodes, AtomCodes,
AtomLength, AtomLength,
BindFromRegister, BindFromRegister,
CallAttributeGoals,
CallContinuation, CallContinuation,
CharCode, CharCode,
CharsToNumber, CharsToNumber,
@@ -179,7 +178,6 @@ pub enum SystemClauseType {
EnqueueAttributedVar, EnqueueAttributedVar,
ExpandGoal, ExpandGoal,
ExpandTerm, ExpandTerm,
FetchAttributeGoals,
FetchGlobalVar, FetchGlobalVar,
FetchGlobalVarWithOffset, FetchGlobalVarWithOffset,
GetChar, GetChar,
@@ -277,7 +275,6 @@ impl SystemClauseType {
&SystemClauseType::AtomCodes => clause_name!("$atom_codes"), &SystemClauseType::AtomCodes => clause_name!("$atom_codes"),
&SystemClauseType::AtomLength => clause_name!("$atom_length"), &SystemClauseType::AtomLength => clause_name!("$atom_length"),
&SystemClauseType::BindFromRegister => clause_name!("$bind_from_register"), &SystemClauseType::BindFromRegister => clause_name!("$bind_from_register"),
&SystemClauseType::CallAttributeGoals => clause_name!("$call_attribute_goals"),
&SystemClauseType::CallContinuation => clause_name!("$call_continuation"), &SystemClauseType::CallContinuation => clause_name!("$call_continuation"),
&SystemClauseType::CharCode => clause_name!("$char_code"), &SystemClauseType::CharCode => clause_name!("$char_code"),
&SystemClauseType::CharsToNumber => clause_name!("$chars_to_number"), &SystemClauseType::CharsToNumber => clause_name!("$chars_to_number"),
@@ -308,7 +305,6 @@ impl SystemClauseType {
&SystemClauseType::EnqueueAttributedVar => clause_name!("$enqueue_attr_var"), &SystemClauseType::EnqueueAttributedVar => clause_name!("$enqueue_attr_var"),
&SystemClauseType::ExpandTerm => clause_name!("$expand_term"), &SystemClauseType::ExpandTerm => clause_name!("$expand_term"),
&SystemClauseType::ExpandGoal => clause_name!("$expand_goal"), &SystemClauseType::ExpandGoal => clause_name!("$expand_goal"),
&SystemClauseType::FetchAttributeGoals => clause_name!("$fetch_attribute_goals"),
&SystemClauseType::FetchGlobalVar => clause_name!("$fetch_global_var"), &SystemClauseType::FetchGlobalVar => clause_name!("$fetch_global_var"),
&SystemClauseType::FetchGlobalVarWithOffset => { &SystemClauseType::FetchGlobalVarWithOffset => {
clause_name!("$fetch_global_var_with_offset") clause_name!("$fetch_global_var_with_offset")
@@ -429,7 +425,6 @@ impl SystemClauseType {
("$module_assertz", 5) => Some(SystemClauseType::ModuleAssertDynamicPredicateToBack), ("$module_assertz", 5) => Some(SystemClauseType::ModuleAssertDynamicPredicateToBack),
("$asserta", 4) => Some(SystemClauseType::AssertDynamicPredicateToFront), ("$asserta", 4) => Some(SystemClauseType::AssertDynamicPredicateToFront),
("$assertz", 4) => Some(SystemClauseType::AssertDynamicPredicateToBack), ("$assertz", 4) => Some(SystemClauseType::AssertDynamicPredicateToBack),
("$call_attribute_goals", 2) => Some(SystemClauseType::CallAttributeGoals),
("$call_continuation", 1) => Some(SystemClauseType::CallContinuation), ("$call_continuation", 1) => Some(SystemClauseType::CallContinuation),
("$char_code", 2) => Some(SystemClauseType::CharCode), ("$char_code", 2) => Some(SystemClauseType::CharCode),
("$chars_to_number", 2) => Some(SystemClauseType::CharsToNumber), ("$chars_to_number", 2) => Some(SystemClauseType::CharsToNumber),
@@ -456,7 +451,6 @@ impl SystemClauseType {
("$is_partial_string", 1) => Some(SystemClauseType::IsPartialString), ("$is_partial_string", 1) => Some(SystemClauseType::IsPartialString),
("$expand_term", 2) => Some(SystemClauseType::ExpandTerm), ("$expand_term", 2) => Some(SystemClauseType::ExpandTerm),
("$expand_goal", 2) => Some(SystemClauseType::ExpandGoal), ("$expand_goal", 2) => Some(SystemClauseType::ExpandGoal),
("$fetch_attribute_goals", 1) => Some(SystemClauseType::FetchAttributeGoals),
("$fetch_global_var", 2) => Some(SystemClauseType::FetchGlobalVar), ("$fetch_global_var", 2) => Some(SystemClauseType::FetchGlobalVar),
("$fetch_global_var_with_offset", 3) => Some(SystemClauseType::FetchGlobalVarWithOffset), ("$fetch_global_var_with_offset", 3) => Some(SystemClauseType::FetchGlobalVarWithOffset),
("$get_char", 1) => Some(SystemClauseType::GetChar), ("$get_char", 1) => Some(SystemClauseType::GetChar),

View File

@@ -446,7 +446,8 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<TermMarker> {
} }
}, },
&InlinedClauseType::IsInteger(..) => match terms[0].as_ref() { &InlinedClauseType::IsInteger(..) => match terms[0].as_ref() {
&Term::Constant(_, Constant::Integer(_)) => { &Term::Constant(_, Constant::Integer(_)) |
&Term::Constant(_, Constant::Fixnum(_)) => {
code.push(succeed!()); code.push(succeed!());
} }
&Term::Var(ref vr, ref name) => { &Term::Var(ref vr, ref name) => {
@@ -511,7 +512,8 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<TermMarker> {
code.push(is_call!(temp_v!(1), at.unwrap_or(interm!(1)))) code.push(is_call!(temp_v!(1), at.unwrap_or(interm!(1))))
} }
} }
&Term::Constant(_, ref c @ Constant::Integer(_)) => { &Term::Constant(_, ref c @ Constant::Integer(_)) |
&Term::Constant(_, ref c @ Constant::Fixnum(_)) => {
code.push(Line::Query(put_constant!( code.push(Line::Query(put_constant!(
Level::Shallow, Level::Shallow,
c.clone(), c.clone(),
@@ -708,7 +710,7 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<TermMarker> {
match fact_instr { match fact_instr {
&mut FactInstruction::UnifyValue(r) => { &mut FactInstruction::UnifyValue(r) => {
if !safe_vars.contains(&r) { if !safe_vars.contains(&r) {
*fact_instr = FactInstruction::UnifyLocalValue(r); *fact_instr = FactInstruction::UnifyLocalValue(r);
safe_vars.insert(r); safe_vars.insert(r);
} }
} }

View File

@@ -12,6 +12,7 @@ use indexmap::IndexMap;
use std::cell::Cell; use std::cell::Cell;
use std::collections::VecDeque; use std::collections::VecDeque;
use std::convert::TryFrom;
use std::path::PathBuf; use std::path::PathBuf;
use std::rc::Rc; use std::rc::Rc;
@@ -573,11 +574,33 @@ pub struct Module {
pub listing_src: ListingSource, pub listing_src: ListingSource,
} }
#[derive(Clone, PartialEq, Eq)] #[derive(Clone)]
pub enum Number { pub enum Number {
Float(OrderedFloat<f64>), Float(OrderedFloat<f64>),
Integer(Rc<Integer>), Integer(Rc<Integer>),
Rational(Rc<Rational>), Rational(Rc<Rational>),
Fixnum(isize),
}
impl From<Integer> for Number {
#[inline]
fn from(n: Integer) -> Self {
Number::Integer(Rc::new(n))
}
}
impl From<Rational> for Number {
#[inline]
fn from(n: Rational) -> Self {
Number::Rational(Rc::new(n))
}
}
impl From<isize> for Number {
#[inline]
fn from(n: isize) -> Self {
Number::Fixnum(n)
}
} }
impl Default for Number { impl Default for Number {
@@ -586,10 +609,23 @@ impl Default for Number {
} }
} }
impl Into<Constant> for Number {
#[inline]
fn into(self) -> Constant {
match self {
Number::Fixnum(n) => Constant::Fixnum(n),
Number::Integer(n) => Constant::Integer(n),
Number::Float(f) => Constant::Float(f),
Number::Rational(r) => Constant::Rational(r),
}
}
}
impl Into<HeapCellValue> for Number { impl Into<HeapCellValue> for Number {
#[inline] #[inline]
fn into(self) -> HeapCellValue { fn into(self) -> HeapCellValue {
match self { match self {
Number::Fixnum(n) => HeapCellValue::Addr(Addr::Fixnum(n)),
Number::Integer(n) => HeapCellValue::Integer(n), Number::Integer(n) => HeapCellValue::Integer(n),
Number::Float(f) => HeapCellValue::Addr(Addr::Float(f)), Number::Float(f) => HeapCellValue::Addr(Addr::Float(f)),
Number::Rational(r) => HeapCellValue::Rational(r), Number::Rational(r) => HeapCellValue::Rational(r),
@@ -597,10 +633,27 @@ impl Into<HeapCellValue> for Number {
} }
} }
impl Number { impl Number {
#[inline]
pub fn to_u32(&self) -> Option<u32> {
match self {
&Number::Fixnum(n) => u32::try_from(n).ok(),
&Number::Integer(ref n) => n.to_u32(),
&Number::Float(_) => None,
&Number::Rational(ref r) =>
if r.denom() == &1 {
r.numer().to_u32()
} else {
None
}
}
}
#[inline] #[inline]
pub fn is_positive(&self) -> bool { pub fn is_positive(&self) -> bool {
match self { match self {
&Number::Fixnum(n) => n > 0,
&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,
@@ -610,6 +663,7 @@ impl Number {
#[inline] #[inline]
pub fn is_negative(&self) -> bool { pub fn is_negative(&self) -> bool {
match self { match self {
&Number::Fixnum(n) => n < 0,
&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,
@@ -619,6 +673,7 @@ impl Number {
#[inline] #[inline]
pub fn is_zero(&self) -> bool { pub fn is_zero(&self) -> bool {
match self { match self {
&Number::Fixnum(n) => n == 0,
&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,
@@ -628,9 +683,15 @@ impl Number {
#[inline] #[inline]
pub fn abs(self) -> Self { pub fn abs(self) -> Self {
match self { match self {
Number::Integer(n) => Number::Integer(Rc::new(Integer::from(n.abs_ref()))), Number::Fixnum(n) =>
if let Some(n) = n.checked_abs() {
Number::from(n)
} else {
Number::from(Integer::from(n).abs())
}
Number::Integer(n) => Number::from(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(Rc::new(Rational::from(r.abs_ref()))), Number::Rational(r) => Number::from(Rational::from(r.abs_ref())),
} }
} }
} }

View File

@@ -12,6 +12,7 @@ use crate::prolog::rug::Integer;
use indexmap::{IndexMap, IndexSet}; use indexmap::{IndexMap, IndexSet};
use std::cell::Cell; use std::cell::Cell;
use std::convert::TryFrom;
use std::iter::{FromIterator, once}; use std::iter::{FromIterator, once};
use std::ops::{Range, RangeFrom}; use std::ops::{Range, RangeFrom};
use std::rc::Rc; use std::rc::Rc;
@@ -263,30 +264,27 @@ 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() && iter.leftmost_leaf_has_property(|addr, heap| { op.is_negative_sign() &&
match addr { iter.leftmost_leaf_has_property(|addr, heap| {
Addr::Con(h) => { match Number::try_from((addr, heap)) {
match &heap[h] { Ok(Number::Fixnum(n)) => {
HeapCellValue::Integer(ref n) => { n > 0
&**n > &0 }
} Ok(Number::Float(f)) => {
&HeapCellValue::Rational(ref r) => { f > OrderedFloat(0f64)
&**r > &0 }
} Ok(Number::Integer(n)) => {
_ => { &*n > &0
false }
} Ok(Number::Rational(n)) => {
&*n > &0
}
_ => {
false
} }
} }
Addr::Float(f) => { })
f > OrderedFloat(0f64)
}
_ => {
false
}
}
})
} else { } else {
false false
} }
@@ -311,14 +309,19 @@ 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)) { let addr = self.store(self.deref(addr));
Addr::Con(h) => {
if let &HeapCellValue::Integer(ref n) = &self.heap[h] { match Number::try_from((addr, &self.heap)) {
if &**n >= &0 { Ok(Number::Fixnum(n)) => {
Some(numbervar(Integer::from(offset + &**n))) if n >= 0 {
} else { Some(numbervar(Integer::from(offset + Integer::from(n))))
None } else {
} None
}
}
Ok(Number::Integer(n)) => {
if &*n >= &0 {
Some(numbervar(Integer::from(offset + &*n)))
} else { } else {
None None
} }
@@ -1336,6 +1339,9 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
&HeapCellValue::Addr(Addr::Float(n)) => { &HeapCellValue::Addr(Addr::Float(n)) => {
self.print_number(Number::Float(n), &op); self.print_number(Number::Float(n), &op);
} }
&HeapCellValue::Addr(Addr::Fixnum(n)) => {
self.print_number(Number::Fixnum(n), &op);
}
&HeapCellValue::Addr(Addr::Usize(u)) => { &HeapCellValue::Addr(Addr::Usize(u)) => {
self.append_str(&format!("{}", u)); self.append_str(&format!("{}", u));
} }

View File

@@ -1,11 +1,13 @@
use prolog_parser::ast::*; use prolog_parser::ast::*;
use crate::prolog::instructions::*; use crate::prolog::instructions::*;
use crate::prolog::rug::Integer;
use indexmap::IndexMap; use indexmap::IndexMap;
use std::collections::VecDeque; use std::collections::VecDeque;
use std::hash::Hash; use std::hash::Hash;
use std::rc::Rc;
#[derive(Clone, Copy)] #[derive(Clone, Copy)]
enum IntIndex { enum IntIndex {
@@ -48,6 +50,41 @@ impl CodeOffsets {
} }
} }
fn intercept_constant(&mut self, constant: &Constant, index: usize) {
match constant {
&Constant::Atom(ref name, _) if name.is_char() => {
let c = name.as_str().chars().next().unwrap();
let code = self.constants
.entry(Constant::Char(c))
.or_insert(vec![]);
code.push(Self::add_index(code.is_empty(), index));
}
&Constant::Fixnum(n) => {
let code = self.constants
.entry(Constant::Integer(Rc::new(Integer::from(n))))
.or_insert(vec![]);
code.push(Self::add_index(code.is_empty(), index));
}
&Constant::Integer(ref n) => {
if let Some(n) = n.to_isize() {
let code = self.constants
.entry(Constant::Fixnum(n))
.or_insert(vec![]);
code.push(Self::add_index(code.is_empty(), index));
}
}
&Constant::String(_) => {
let is_initial_index = self.lists.is_empty();
self.lists.push(Self::add_index(is_initial_index, index));
}
_ => {
}
}
}
pub fn index_term(&mut self, first_arg: &Term, index: usize) { pub fn index_term(&mut self, first_arg: &Term, index: usize) {
match first_arg { match first_arg {
&Term::Clause(_, ref name, ref terms, _) => { &Term::Clause(_, ref name, ref terms, _) => {
@@ -63,29 +100,12 @@ 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(ref s)) => {
let is_initial_index = self.lists.is_empty();
self.lists.push(Self::add_index(is_initial_index, index));
let constant = Constant::String(s.clone());
let code = self.constants.entry(constant).or_insert(Vec::new());
let is_initial_index = code.is_empty();
code.push(Self::add_index(is_initial_index, index));
}
&Term::Constant(_, ref constant) => { &Term::Constant(_, ref constant) => {
if let Constant::Atom(ref name, _) = constant { self.intercept_constant(constant, index);
if name.is_char() {
let c = name.as_str().chars().next().unwrap(); let code = self.constants
let code = self.constants .entry(constant.clone())
.entry(Constant::Char(c)) .or_insert(vec![]);
.or_insert(vec![]);
code.push(Self::add_index(code.is_empty(), index));
}
}
let code = self.constants.entry(constant.clone()).or_insert(Vec::new());
let is_initial_index = code.is_empty(); let is_initial_index = code.is_empty();
code.push(Self::add_index(is_initial_index, index)); code.push(Self::add_index(is_initial_index, index));

View File

@@ -63,12 +63,12 @@ Assocs are Key-Value associations implemented as a balanced binary tree
@author R.A.O'Keefe, L.Damas, V.S.Costa and Jan Wielemaker @author R.A.O'Keefe, L.Damas, V.S.Costa and Jan Wielemaker
*/ */
/* /*
:- meta_predicate :- meta_predicate
map_assoc(1, ?), map_assoc(1, ?),
map_assoc(2, ?, ?). map_assoc(2, ?, ?).
*/ */
%! empty_assoc(?Assoc) is semidet. %! empty_assoc(?Assoc) is semidet.
% %
% Is true if Assoc is the empty association list. % Is true if Assoc is the empty association list.

View File

@@ -1024,7 +1024,7 @@ subsumes_term(General, Specific) :-
unify_with_occurs_check(X, Y) :- '$unify_with_occurs_check'(X, Y). unify_with_occurs_check(X, Y) :- '$unify_with_occurs_check'(X, Y).
current_input(S) :- '$current_input'(S). current_input(S) :- '$current_input'(S).
current_output(S) :- '$current_output'(S). current_output(S) :- '$current_output'(S).

File diff suppressed because it is too large Load Diff

View File

@@ -6,6 +6,8 @@ use crate::prolog::machine::compile::*;
use crate::prolog::machine::machine_errors::*; use crate::prolog::machine::machine_errors::*;
use crate::prolog::machine::streams::*; use crate::prolog::machine::streams::*;
use std::convert::TryFrom;
impl Machine { impl Machine {
pub(super) fn atom_tbl_of(&self, name: &ClauseName) -> TabledData<Atom> { pub(super) fn atom_tbl_of(&self, name: &ClauseName) -> TabledData<Atom> {
match name { match name {
@@ -52,10 +54,16 @@ impl Machine {
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(h) => { Addr::Con(h) => {
if let HeapCellValue::Integer(ref arity) = &self.machine_st.heap[h] { match &self.machine_st.heap[h] {
arity.to_usize().unwrap() HeapCellValue::Integer(ref arity) => {
} else { arity.to_usize().unwrap()
unreachable!() }
HeapCellValue::Addr(Addr::Fixnum(arity)) => {
usize::try_from(*arity).unwrap()
}
_ => {
unreachable!()
}
} }
} }
Addr::Usize(n) => { Addr::Usize(n) => {
@@ -102,12 +110,12 @@ impl Machine {
} }
} }
} }
fn abolish_dynamic_clause(&mut self, name: RegType, arity: RegType) { fn abolish_dynamic_clause(&mut self, name: RegType, arity: RegType) {
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);
} }
@@ -155,7 +163,7 @@ impl Machine {
name, name,
arity, arity,
); );
self.machine_st = machine_st; self.machine_st = machine_st;
if let EvalSession::Error(err) = result { if let EvalSession::Error(err) = result {
@@ -239,11 +247,17 @@ impl Machine {
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(h) => Addr::Con(h) =>
if let HeapCellValue::Integer(ref n) = &self.machine_st.heap[h] { match &self.machine_st.heap[h] {
n.to_usize().unwrap() HeapCellValue::Integer(ref arity) => {
} else { arity.to_usize().unwrap()
unreachable!() }
}, HeapCellValue::Addr(Addr::Fixnum(arity)) => {
usize::try_from(*arity).unwrap()
}
_ => {
unreachable!()
}
}
_ => unreachable!(), _ => unreachable!(),
}; };
@@ -260,7 +274,7 @@ impl Machine {
if addrs.is_empty() { if addrs.is_empty() {
self.make_undefined(name.clone(), arity); self.make_undefined(name.clone(), arity);
} }
self.print_new_dynamic_clause(addrs, name.clone(), arity) self.print_new_dynamic_clause(addrs, name.clone(), arity)
} }
Err(err) => { Err(err) => {
@@ -280,12 +294,19 @@ 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(h) => Addr::Con(h) => {
if let HeapCellValue::Integer(n) = &self.machine_st.heap[h] { match &self.machine_st.heap[h] {
n.to_usize().unwrap() HeapCellValue::Integer(ref arity) => {
} else { arity.to_usize().unwrap()
unreachable!() }
}, HeapCellValue::Addr(Addr::Fixnum(arity)) => {
usize::try_from(*arity).unwrap()
}
_ => {
unreachable!()
}
}
}
_ => { _ => {
unreachable!() unreachable!()
} }
@@ -302,7 +323,7 @@ impl Machine {
if addrs.is_empty() { if addrs.is_empty() {
self.make_undefined(name.clone(), arity); self.make_undefined(name.clone(), arity);
} }
self.print_new_dynamic_clause(addrs, name.clone(), arity) self.print_new_dynamic_clause(addrs, name.clone(), arity)
} }
Err(err) => { Err(err) => {

View File

@@ -6,6 +6,7 @@ use crate::prolog::machine::machine_indices::*;
use crate::prolog::machine::partial_string::*; use crate::prolog::machine::partial_string::*;
use crate::prolog::machine::raw_block::*; use crate::prolog::machine::raw_block::*;
use std::convert::TryFrom;
use std::mem; use std::mem;
use std::ops::{Index, IndexMut}; use std::ops::{Index, IndexMut};
use std::ptr; use std::ptr;
@@ -202,6 +203,9 @@ impl<T: RawBlockTraits> HeapTemplate<T> {
Constant::EmptyList => { Constant::EmptyList => {
Addr::EmptyList Addr::EmptyList
} }
Constant::Fixnum(n) => {
Addr::Fixnum(n)
}
Constant::Integer(n) => { Constant::Integer(n) => {
Addr::Con(self.push(HeapCellValue::Integer(n))) Addr::Con(self.push(HeapCellValue::Integer(n)))
} }
@@ -252,26 +256,6 @@ impl<T: RawBlockTraits> HeapTemplate<T> {
h 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] #[inline]
pub(crate) pub(crate)
fn atom_at(&self, h: usize) -> bool { fn atom_at(&self, h: usize) -> bool {
@@ -475,6 +459,7 @@ impl<T: RawBlockTraits> HeapTemplate<T> {
fn to_local_code_ptr(&self, addr: &Addr) -> Option<LocalCodePtr> { 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] { match &self[s] {
&HeapCellValue::Addr(Addr::Fixnum(n)) => usize::try_from(n).ok(),
&HeapCellValue::Integer(ref n) => n.to_usize(), &HeapCellValue::Integer(ref n) => n.to_usize(),
_ => None _ => None
} }

View File

@@ -20,6 +20,7 @@ use indexmap::IndexMap;
use std::cell::RefCell; use std::cell::RefCell;
use std::cmp::Ordering; use std::cmp::Ordering;
use std::collections::{BTreeMap, VecDeque}; use std::collections::{BTreeMap, VecDeque};
use std::convert::TryFrom;
use std::mem; use std::mem;
use std::ops::{Add, AddAssign, Sub, SubAssign}; use std::ops::{Add, AddAssign, Sub, SubAssign};
use std::rc::Rc; use std::rc::Rc;
@@ -59,6 +60,7 @@ pub enum Addr {
Con(usize), Con(usize),
CutPoint(usize), CutPoint(usize),
EmptyList, EmptyList,
Fixnum(isize),
Float(OrderedFloat<f64>), Float(OrderedFloat<f64>),
Lis(usize), Lis(usize),
HeapCell(usize), HeapCell(usize),
@@ -155,8 +157,9 @@ impl Addr {
#[inline] #[inline]
pub fn is_heap_bound(&self) -> bool { pub fn is_heap_bound(&self) -> bool {
match self { match self {
Addr::Char(_) | Addr::CharCode(_) | Addr::EmptyList Addr::Char(_) | Addr::CharCode(_) | Addr::EmptyList |
| Addr::CutPoint(_) | Addr::Usize(_) | Addr::Float(_) => { Addr::CutPoint(_) | Addr::Usize(_) | Addr::Fixnum(_) |
Addr::Float(_) => {
false false
} }
_ => { _ => {
@@ -189,43 +192,47 @@ impl Addr {
pub(super) pub(super)
fn order_category(&self, heap: &Heap) -> Option<TermOrderCategory> { fn order_category(&self, heap: &Heap) -> Option<TermOrderCategory> {
match self { match Number::try_from((*self, heap)) {
Addr::HeapCell(_) | Addr::AttrVar(_) | Addr::StackCell(..) => { Ok(Number::Integer(_)) | Ok(Number::Fixnum(_)) | Ok(Number::Rational(_)) => {
Some(TermOrderCategory::Variable)
}
Addr::Float(_) => {
Some(TermOrderCategory::FloatingPoint)
}
&Addr::Con(h) => {
match &heap[h] {
HeapCellValue::Atom(..) => {
Some(TermOrderCategory::Atom)
}
HeapCellValue::Integer(_) => {
Some(TermOrderCategory::Integer)
}
HeapCellValue::Rational(_) => {
Some(TermOrderCategory::Integer)
}
HeapCellValue::DBRef(_) => {
None
}
_ => {
unreachable!()
}
}
}
Addr::Char(_) | Addr::EmptyList => {
Some(TermOrderCategory::Atom)
}
Addr::Usize(_) | Addr::CharCode(_) => {
Some(TermOrderCategory::Integer) Some(TermOrderCategory::Integer)
} }
Addr::Lis(_) | Addr::PStrLocation(..) | Addr::Str(_) => { Ok(Number::Float(_)) => {
Some(TermOrderCategory::Compound) Some(TermOrderCategory::FloatingPoint)
} }
Addr::CutPoint(_) | Addr::Stream(_) => { _ => {
None match self {
Addr::HeapCell(_) | Addr::AttrVar(_) | Addr::StackCell(..) => {
Some(TermOrderCategory::Variable)
}
Addr::Float(_) => {
Some(TermOrderCategory::FloatingPoint)
}
&Addr::Con(h) => {
match &heap[h] {
HeapCellValue::Atom(..) => {
Some(TermOrderCategory::Atom)
}
HeapCellValue::DBRef(_) => {
None
}
_ => {
unreachable!()
}
}
}
Addr::Char(_) | Addr::EmptyList => {
Some(TermOrderCategory::Atom)
}
Addr::CharCode(_) | Addr::Fixnum(_) | Addr::Usize(_) => {
Some(TermOrderCategory::Integer)
}
Addr::Lis(_) | Addr::PStrLocation(..) | Addr::Str(_) => {
Some(TermOrderCategory::Compound)
}
Addr::CutPoint(_) | Addr::Stream(_) => {
None
}
}
} }
} }
} }
@@ -257,13 +264,16 @@ impl Addr {
&Addr::EmptyList => { &Addr::EmptyList => {
Some(Constant::EmptyList) Some(Constant::EmptyList)
} }
&Addr::Fixnum(n) => {
Some(Constant::Fixnum(n))
}
&Addr::Float(f) => { &Addr::Float(f) => {
Some(Constant::Float(f)) Some(Constant::Float(f))
} }
&Addr::PStrLocation(h, n) => { &Addr::PStrLocation(h, n) => {
let mut heap_pstr_iter = let mut heap_pstr_iter =
machine_st.heap_pstr_iter(Addr::PStrLocation(h, n)); machine_st.heap_pstr_iter(Addr::PStrLocation(h, n));
let mut buf = String::new(); let mut buf = String::new();
while let Some(Some(c)) = heap_pstr_iter.next() { while let Some(Some(c)) = heap_pstr_iter.next() {

View File

@@ -56,7 +56,7 @@ impl<'a> Iterator for HeapPStrIter<'a> {
} else { } else {
return None; return None;
} }
match addr { match addr {
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] {
@@ -72,7 +72,7 @@ impl<'a> Iterator for HeapPStrIter<'a> {
} }
Addr::Lis(l) => { Addr::Lis(l) => {
let addr = self.machine_st.store(self.machine_st.deref(Addr::HeapCell(l))); let addr = self.machine_st.store(self.machine_st.deref(Addr::HeapCell(l)));
if let Addr::Char(c) = addr { if let Addr::Char(c) = addr {
self.focus = Addr::HeapCell(l + 1); self.focus = Addr::HeapCell(l + 1);
return Some(Some(c)); return Some(Some(c));
@@ -96,7 +96,7 @@ pub(super)
fn compare_pstr<'a>( fn compare_pstr<'a>(
pstr_iter: HeapPStrIter<'a>, pstr_iter: HeapPStrIter<'a>,
mut c_iter: impl Iterator<Item = char>, mut c_iter: impl Iterator<Item = char>,
) -> bool { ) -> bool {
for opt_c in pstr_iter { for opt_c in pstr_iter {
match opt_c { match opt_c {
Some(_) => { Some(_) => {
@@ -965,7 +965,7 @@ pub(crate) trait CallPolicy: Any {
let a1 = machine_st[r]; let a1 = machine_st[r];
let n2 = machine_st.get_number(at)?; let n2 = machine_st.get_number(at)?;
let n2 = Addr::Con(machine_st.heap.push(n2.into())); let n2 = machine_st.heap.put_constant(n2.into());
machine_st.unify(a1, n2); machine_st.unify(a1, n2);
return_from_clause!(machine_st.last_call, machine_st) return_from_clause!(machine_st.last_call, machine_st)

View File

@@ -21,6 +21,7 @@ use crate::prolog::rug::Integer;
use indexmap::{IndexMap, IndexSet}; use indexmap::{IndexMap, IndexSet};
use std::cmp::Ordering; use std::cmp::Ordering;
use std::convert::TryFrom;
use std::rc::Rc; use std::rc::Rc;
macro_rules! try_or_fail { macro_rules! try_or_fail {
@@ -261,8 +262,8 @@ impl MachineState {
self.fail = true; self.fail = true;
} }
(Addr::PStrLocation(h, n), Addr::Lis(l)) (Addr::PStrLocation(h, n), Addr::Lis(l)) |
| (Addr::Lis(l), Addr::PStrLocation(h, n)) => { (Addr::Lis(l), Addr::PStrLocation(h, n)) => {
if let HeapCellValue::PartialString(ref pstr, _) = &self.heap[h] { if let HeapCellValue::PartialString(ref pstr, _) = &self.heap[h] {
if let Some(c) = pstr.range_from(n ..).next() { if let Some(c) = pstr.range_from(n ..).next() {
pdl.push(Addr::PStrLocation(h, n + c.len_utf8())); pdl.push(Addr::PStrLocation(h, n + c.len_utf8()));
@@ -369,16 +370,17 @@ impl MachineState {
) if db_ref_1 == db_ref_2 => { ) if db_ref_1 == db_ref_2 => {
} }
( (
&HeapCellValue::Integer(ref n1), v1,
&HeapCellValue::Integer(ref n2), v2,
) if &**n1 == &**n2 => { ) => {
} if let Ok(n1) = Number::try_from(v1) {
( if let Ok(n2) = Number::try_from(v2) {
&HeapCellValue::Rational(ref n1), if n1 == n2 {
&HeapCellValue::Rational(ref n2), continue;
) if &**n1 == &**n2 => { }
} }
_ => { }
self.fail = true; self.fail = true;
} }
} }
@@ -397,34 +399,31 @@ impl MachineState {
} }
} }
} }
(Addr::Usize(n1), Addr::Con(n2)) | (Addr::Con(n2), Addr::Usize(n1)) => {
if let HeapCellValue::Integer(ref n2) = &self.heap[n2] {
if let Some(n2) = n2.to_usize() {
if n1 == n2 {
continue;
}
}
}
self.fail = true;
}
(Addr::CharCode(n1), Addr::Con(n2)) | (Addr::Con(n2), Addr::CharCode(n1)) => {
if let HeapCellValue::Integer(ref n2) = &self.heap[n2] {
if let Some(n2) = n2.to_u32() {
if n1 == n2 {
continue;
}
}
}
self.fail = true;
}
(Addr::Stream(s1), Addr::Stream(s2)) => { (Addr::Stream(s1), Addr::Stream(s2)) => {
if s1 != s2 { if s1 != s2 {
self.fail = true; self.fail = true;
} }
} }
(v, Addr::Con(h)) | (Addr::Con(h), v) => {
if let Ok(n1) = Number::try_from(&self.heap[h]) {
if let Ok(v) = Number::try_from(&HeapCellValue::Addr(v)) {
if n1 == v {
continue;
}
}
}
self.fail = true;
}
(a1, a2) => { (a1, a2) => {
if let Ok(n1) = Number::try_from(&HeapCellValue::Addr(a1)) {
if let Ok(n2) = Number::try_from(&HeapCellValue::Addr(a2)) {
if n1 == n2 {
continue;
}
}
}
if a1 != a2 { if a1 != a2 {
self.fail = true; self.fail = true;
} }
@@ -481,8 +480,8 @@ impl MachineState {
self.fail = true; self.fail = true;
} }
(Addr::PStrLocation(h, n), Addr::Lis(l)) (Addr::PStrLocation(h, n), Addr::Lis(l)) |
| (Addr::Lis(l), Addr::PStrLocation(h, n)) => { (Addr::Lis(l), Addr::PStrLocation(h, n)) => {
if let HeapCellValue::PartialString(ref pstr, _) = &self.heap[h] { if let HeapCellValue::PartialString(ref pstr, _) = &self.heap[h] {
if let Some(c) = pstr.range_from(n ..).next() { if let Some(c) = pstr.range_from(n ..).next() {
pdl.push(Addr::PStrLocation(h, n + c.len_utf8())); pdl.push(Addr::PStrLocation(h, n + c.len_utf8()));
@@ -585,16 +584,17 @@ impl MachineState {
) if db_ref_1 == db_ref_2 => { ) if db_ref_1 == db_ref_2 => {
} }
( (
&HeapCellValue::Integer(ref n1), v1,
&HeapCellValue::Integer(ref n2), v2,
) if &**n1 == &**n2 => { ) => {
} if let Ok(n1) = Number::try_from(v1) {
( if let Ok(n2) = Number::try_from(v2) {
&HeapCellValue::Rational(ref n1), if n1 == n2 {
&HeapCellValue::Rational(ref n2), continue;
) if &**n1 == &**n2 => { }
} }
_ => { }
self.fail = true; self.fail = true;
} }
} }
@@ -613,34 +613,31 @@ impl MachineState {
} }
} }
} }
(Addr::Usize(n1), Addr::Con(n2)) | (Addr::Con(n2), Addr::Usize(n1)) => {
if let HeapCellValue::Integer(ref n2) = &self.heap[n2] {
if let Some(n2) = n2.to_usize() {
if n1 == n2 {
continue;
}
}
}
self.fail = true;
}
(Addr::CharCode(n1), Addr::Con(n2)) | (Addr::Con(n2), Addr::CharCode(n1)) => {
if let HeapCellValue::Integer(ref n2) = &self.heap[n2] {
if let Some(n2) = n2.to_u32() {
if n1 == n2 {
continue;
}
}
}
self.fail = true;
}
(Addr::Stream(s1), Addr::Stream(s2)) => { (Addr::Stream(s1), Addr::Stream(s2)) => {
if s1 != s2 { if s1 != s2 {
self.fail = true; self.fail = true;
} }
} }
(v, Addr::Con(h)) | (Addr::Con(h), v) => {
if let Ok(n1) = Number::try_from(&self.heap[h]) {
if let Ok(v) = Number::try_from(&HeapCellValue::Addr(v)) {
if n1 == v {
continue;
}
}
}
self.fail = true;
}
(a1, a2) => { (a1, a2) => {
if let Ok(n1) = Number::try_from(&HeapCellValue::Addr(a1)) {
if let Ok(n2) = Number::try_from(&HeapCellValue::Addr(a2)) {
if n1 == n2 {
continue;
}
}
}
if a1 != a2 { if a1 != a2 {
self.fail = true; self.fail = true;
} }
@@ -791,6 +788,9 @@ impl MachineState {
} }
HeapCellValue::Integer(ref n1) => { HeapCellValue::Integer(ref n1) => {
match c { match c {
Constant::Fixnum(n2) => {
n1.to_isize() != Some(*n2)
}
Constant::Integer(ref n2) => { Constant::Integer(ref n2) => {
n1 != n2 n1 != n2
} }
@@ -919,8 +919,7 @@ impl MachineState {
let n1 = try_or_fail!(self, self.get_number(a1)); let n1 = try_or_fail!(self, self.get_number(a1));
let n2 = try_or_fail!(self, self.get_number(a2)); let n2 = try_or_fail!(self, self.get_number(a2));
self.interms[t - 1] = self.interms[t - 1] = try_or_fail!(self, self.gcd(n1, n2));
Number::Integer(Rc::new(try_or_fail!(self, self.gcd(n1, n2))));
self.p += 1; self.p += 1;
} }
&ArithmeticInstruction::Pow(ref a1, ref a2, t) => { &ArithmeticInstruction::Pow(ref a1, ref a2, t) => {
@@ -944,16 +943,14 @@ impl MachineState {
let n1 = try_or_fail!(self, self.get_number(a1)); let n1 = try_or_fail!(self, self.get_number(a1));
let n2 = try_or_fail!(self, self.get_number(a2)); let n2 = try_or_fail!(self, self.get_number(a2));
self.interms[t - 1] = self.interms[t - 1] = try_or_fail!(self, self.int_floor_div(n1, n2));
Number::Integer(Rc::new(try_or_fail!(self, self.int_floor_div(n1, n2))));
self.p += 1; self.p += 1;
} }
&ArithmeticInstruction::IDiv(ref a1, ref a2, t) => { &ArithmeticInstruction::IDiv(ref a1, ref a2, t) => {
let n1 = try_or_fail!(self, self.get_number(a1)); let n1 = try_or_fail!(self, self.get_number(a1));
let n2 = try_or_fail!(self, self.get_number(a2)); let n2 = try_or_fail!(self, self.get_number(a2));
self.interms[t - 1] = self.interms[t - 1] = try_or_fail!(self, self.idiv(n1, n2));
Number::Integer(Rc::new(try_or_fail!(self, self.idiv(n1, n2))));
self.p += 1; self.p += 1;
} }
&ArithmeticInstruction::Abs(ref a1, t) => { &ArithmeticInstruction::Abs(ref a1, t) => {
@@ -965,7 +962,7 @@ impl MachineState {
&ArithmeticInstruction::Sign(ref a1, t) => { &ArithmeticInstruction::Sign(ref a1, t) => {
let n = try_or_fail!(self, self.get_number(a1)); let n = try_or_fail!(self, self.get_number(a1));
self.interms[t - 1] = Number::Integer(Rc::new(self.sign(n))); self.interms[t - 1] = self.sign(n);
self.p += 1; self.p += 1;
} }
&ArithmeticInstruction::Neg(ref a1, t) => { &ArithmeticInstruction::Neg(ref a1, t) => {
@@ -977,8 +974,7 @@ impl MachineState {
&ArithmeticInstruction::BitwiseComplement(ref a1, t) => { &ArithmeticInstruction::BitwiseComplement(ref a1, t) => {
let n1 = try_or_fail!(self, self.get_number(a1)); let n1 = try_or_fail!(self, self.get_number(a1));
self.interms[t - 1] = self.interms[t - 1] = try_or_fail!(self, self.bitwise_complement(n1));
Number::Integer(Rc::new(try_or_fail!(self, self.bitwise_complement(n1))));
self.p += 1; self.p += 1;
} }
&ArithmeticInstruction::Div(ref a1, ref a2, t) => { &ArithmeticInstruction::Div(ref a1, ref a2, t) => {
@@ -992,56 +988,49 @@ impl MachineState {
let n1 = try_or_fail!(self, self.get_number(a1)); let n1 = try_or_fail!(self, self.get_number(a1));
let n2 = try_or_fail!(self, self.get_number(a2)); let n2 = try_or_fail!(self, self.get_number(a2));
self.interms[t - 1] = self.interms[t - 1] = try_or_fail!(self, self.shr(n1, n2));
Number::Integer(Rc::new(try_or_fail!(self, self.shr(n1, n2))));
self.p += 1; self.p += 1;
} }
&ArithmeticInstruction::Shl(ref a1, ref a2, t) => { &ArithmeticInstruction::Shl(ref a1, ref a2, t) => {
let n1 = try_or_fail!(self, self.get_number(a1)); let n1 = try_or_fail!(self, self.get_number(a1));
let n2 = try_or_fail!(self, self.get_number(a2)); let n2 = try_or_fail!(self, self.get_number(a2));
self.interms[t - 1] = self.interms[t - 1] = try_or_fail!(self, self.shl(n1, n2));
Number::Integer(Rc::new(try_or_fail!(self, self.shl(n1, n2))));
self.p += 1; self.p += 1;
} }
&ArithmeticInstruction::Xor(ref a1, ref a2, t) => { &ArithmeticInstruction::Xor(ref a1, ref a2, t) => {
let n1 = try_or_fail!(self, self.get_number(a1)); let n1 = try_or_fail!(self, self.get_number(a1));
let n2 = try_or_fail!(self, self.get_number(a2)); let n2 = try_or_fail!(self, self.get_number(a2));
self.interms[t - 1] = self.interms[t - 1] = try_or_fail!(self, self.xor(n1, n2));
Number::Integer(Rc::new(try_or_fail!(self, self.xor(n1, n2))));
self.p += 1; self.p += 1;
} }
&ArithmeticInstruction::And(ref a1, ref a2, t) => { &ArithmeticInstruction::And(ref a1, ref a2, t) => {
let n1 = try_or_fail!(self, self.get_number(a1)); let n1 = try_or_fail!(self, self.get_number(a1));
let n2 = try_or_fail!(self, self.get_number(a2)); let n2 = try_or_fail!(self, self.get_number(a2));
self.interms[t - 1] = self.interms[t - 1] = try_or_fail!(self, self.and(n1, n2));
Number::Integer(Rc::new(try_or_fail!(self, self.and(n1, n2))));
self.p += 1; self.p += 1;
} }
&ArithmeticInstruction::Or(ref a1, ref a2, t) => { &ArithmeticInstruction::Or(ref a1, ref a2, t) => {
let n1 = try_or_fail!(self, self.get_number(a1)); let n1 = try_or_fail!(self, self.get_number(a1));
let n2 = try_or_fail!(self, self.get_number(a2)); let n2 = try_or_fail!(self, self.get_number(a2));
self.interms[t - 1] = self.interms[t - 1] = try_or_fail!(self, self.or(n1, n2));
Number::Integer(Rc::new(try_or_fail!(self, self.or(n1, n2))));
self.p += 1; self.p += 1;
} }
&ArithmeticInstruction::Mod(ref a1, ref a2, t) => { &ArithmeticInstruction::Mod(ref a1, ref a2, t) => {
let n1 = try_or_fail!(self, self.get_number(a1)); let n1 = try_or_fail!(self, self.get_number(a1));
let n2 = try_or_fail!(self, self.get_number(a2)); let n2 = try_or_fail!(self, self.get_number(a2));
self.interms[t - 1] = self.interms[t - 1] = try_or_fail!(self, self.modulus(n1, n2));
Number::Integer(Rc::new(try_or_fail!(self, self.modulus(n1, n2))));
self.p += 1; self.p += 1;
} }
&ArithmeticInstruction::Rem(ref a1, ref a2, t) => { &ArithmeticInstruction::Rem(ref a1, ref a2, t) => {
let n1 = try_or_fail!(self, self.get_number(a1)); let n1 = try_or_fail!(self, self.get_number(a1));
let n2 = try_or_fail!(self, self.get_number(a2)); let n2 = try_or_fail!(self, self.get_number(a2));
self.interms[t - 1] = self.interms[t - 1] = try_or_fail!(self, self.remainder(n1, n2));
Number::Integer(Rc::new(try_or_fail!(self, self.remainder(n1, n2))));
self.p += 1; self.p += 1;
} }
&ArithmeticInstruction::Cos(ref a1, t) => { &ArithmeticInstruction::Cos(ref a1, t) => {
@@ -1120,29 +1109,25 @@ impl MachineState {
&ArithmeticInstruction::Truncate(ref a1, t) => { &ArithmeticInstruction::Truncate(ref a1, t) => {
let n1 = try_or_fail!(self, self.get_number(a1)); let n1 = try_or_fail!(self, self.get_number(a1));
self.interms[t - 1] = self.interms[t - 1] = self.truncate(n1);
Number::Integer(Rc::new(self.truncate(n1)));
self.p += 1; self.p += 1;
} }
&ArithmeticInstruction::Round(ref a1, t) => { &ArithmeticInstruction::Round(ref a1, t) => {
let n1 = try_or_fail!(self, self.get_number(a1)); let n1 = try_or_fail!(self, self.get_number(a1));
self.interms[t - 1] = self.interms[t - 1] = try_or_fail!(self, self.round(n1));
Number::Integer(Rc::new(try_or_fail!(self, self.round(n1))));
self.p += 1; self.p += 1;
} }
&ArithmeticInstruction::Ceiling(ref a1, t) => { &ArithmeticInstruction::Ceiling(ref a1, t) => {
let n1 = try_or_fail!(self, self.get_number(a1)); let n1 = try_or_fail!(self, self.get_number(a1));
self.interms[t - 1] = self.interms[t - 1] = self.ceiling(n1);
Number::Integer(Rc::new(self.ceiling(n1)));
self.p += 1; self.p += 1;
} }
&ArithmeticInstruction::Floor(ref a1, t) => { &ArithmeticInstruction::Floor(ref a1, t) => {
let n1 = try_or_fail!(self, self.get_number(a1)); let n1 = try_or_fail!(self, self.get_number(a1));
self.interms[t - 1] = self.interms[t - 1] = self.floor(n1);
Number::Integer(Rc::new(self.floor(n1)));
self.p += 1; self.p += 1;
} }
&ArithmeticInstruction::Plus(ref a1, t) => { &ArithmeticInstruction::Plus(ref a1, t) => {
@@ -1332,7 +1317,7 @@ impl MachineState {
} }
} }
Addr::Char(_) | Addr::CharCode(_) | Addr::Con(_) | Addr::CutPoint(_) | Addr::Char(_) | Addr::CharCode(_) | Addr::Con(_) | Addr::CutPoint(_) |
Addr::EmptyList | Addr::Float(_) | Addr::Usize(_) => { Addr::EmptyList | Addr::Fixnum(_) | Addr::Float(_) | Addr::Usize(_) => {
c c
} }
Addr::Lis(_) => { Addr::Lis(_) => {
@@ -1624,19 +1609,35 @@ impl MachineState {
Addr::HeapCell(_) | Addr::StackCell(..) => { // 8.5.2.3 a) Addr::HeapCell(_) | Addr::StackCell(..) => { // 8.5.2.3 a)
return Err(self.error_form(MachineError::instantiation_error(), stub)) return Err(self.error_form(MachineError::instantiation_error(), stub))
} }
Addr::Con(h) => { addr => {
if let HeapCellValue::Integer(n) = self.heap.clone(h) { let n =
if &*n < &0 { // 8.5.2.3 e) match Number::try_from((addr, &self.heap)) {
let n = Number::Integer(n); Ok(Number::Fixnum(n)) => Integer::from(n),
let dom_err = MachineError::domain_error( Ok(Number::Integer(n)) => Integer::from(n.as_ref()),
DomainErrorType::NotLessThanZero, _ => {
n, return Err(self.error_form(
); MachineError::type_error(
self.heap.h(),
ValidType::Integer,
addr,
),
stub,
));
}
};
return Err(self.error_form(dom_err, stub)); if n < 0 { // 8.5.2.3 e)
} let n = Number::from(n);
let dom_err = MachineError::domain_error(
DomainErrorType::NotLessThanZero,
n,
);
let n = match n.to_usize() { return Err(self.error_form(dom_err, stub));
}
let n =
match n.to_usize() {
Some(n) => n, Some(n) => n,
None => { None => {
self.fail = true; self.fail = true;
@@ -1644,88 +1645,68 @@ impl MachineState {
} }
}; };
let term = self.store(self.deref(self[temp_v!(2)])); let term = self.store(self.deref(self[temp_v!(2)]));
match term { match term {
Addr::HeapCell(_) | Addr::StackCell(..) => { // 8.5.2.3 b) Addr::HeapCell(_) | Addr::StackCell(..) | Addr::AttrVar(_) => { // 8.5.2.3 b)
return Err(self.error_form(MachineError::instantiation_error(), stub)) return Err(self.error_form(MachineError::instantiation_error(), stub))
}
Addr::Str(o) => match self.heap.clone(o) {
HeapCellValue::NamedStr(arity, _, _) if 1 <= n && n <= arity => {
let a3 = self[temp_v!(3)];
let h_a = Addr::HeapCell(o + n);
self.unify(a3, h_a);
} }
Addr::Str(o) => match self.heap.clone(o) { _ => {
HeapCellValue::NamedStr(arity, _, _) if 1 <= n && n <= arity => { self.fail = true;
let a3 = self[temp_v!(3)];
let h_a = Addr::HeapCell(o + n);
self.unify(a3, h_a);
}
_ => {
self.fail = true;
}
},
Addr::Lis(l) => {
if n == 1 || n == 2 {
let a3 = self[temp_v!(3)];
let h_a = Addr::HeapCell(l + n - 1);
self.unify(a3, h_a);
} else {
self.fail = true;
}
} }
Addr::PStrLocation(h, offset) => { },
if n == 1 || n == 2 { Addr::Lis(l) => {
let a3 = self[temp_v!(3)]; if n == 1 || n == 2 {
let h_a = let a3 = self[temp_v!(3)];
if let HeapCellValue::PartialString(ref pstr, _) = &self.heap[h] { let h_a = Addr::HeapCell(l + n - 1);
if let Some(c) = pstr.range_from(offset ..).next() {
if n == 1 { self.unify(a3, h_a);
Addr::Char(c) } else {
} else { self.fail = true;
Addr::PStrLocation(h, offset + c.len_utf8()) }
} }
Addr::PStrLocation(h, offset) => {
if n == 1 || n == 2 {
let a3 = self[temp_v!(3)];
let h_a =
if let HeapCellValue::PartialString(ref pstr, _) = &self.heap[h] {
if let Some(c) = pstr.range_from(offset ..).next() {
if n == 1 {
Addr::Char(c)
} else { } else {
unreachable!() Addr::PStrLocation(h, offset + c.len_utf8())
} }
} else { } else {
unreachable!() unreachable!()
}; }
} else {
unreachable!()
};
self.unify(a3, h_a); self.unify(a3, h_a);
} else { } else {
self.fail = true; self.fail = true;
}
}
_ => { // 8.5.2.3 d)
return Err(self.error_form(
MachineError::type_error(
self.heap.h(),
ValidType::Compound,
term,
),
stub,
))
} }
} }
} else { _ => { // 8.5.2.3 d)
return Err(self.error_form( return Err(self.error_form(
MachineError::type_error( MachineError::type_error(
self.heap.h(), self.heap.h(),
ValidType::Integer, ValidType::Compound,
Addr::HeapCell(h), term,
), ),
stub, stub,
)) ))
}
} }
} }
_ => { // 8.5.2.3 c)
return Err(self.error_form(
MachineError::type_error(
self.heap.h(),
ValidType::Integer,
n,
),
stub,
))
}
} }
Ok(()) Ok(())
@@ -1747,7 +1728,8 @@ impl MachineState {
self.p += 1; self.p += 1;
} }
pub(super) fn compare_term(&mut self, qt: CompareTermQT) { pub(super)
fn compare_term(&mut self, qt: CompareTermQT) {
let a1 = self[temp_v!(1)]; let a1 = self[temp_v!(1)];
let a2 = self[temp_v!(2)]; let a2 = self[temp_v!(2)];
@@ -1804,18 +1786,10 @@ impl MachineState {
(Addr::Con(h1), Addr::Con(h2)) => { (Addr::Con(h1), Addr::Con(h2)) => {
match (&self.heap[h1], &self.heap[h2]) { match (&self.heap[h1], &self.heap[h2]) {
( (
&HeapCellValue::Integer(ref n1), &HeapCellValue::Atom(ref n1, ref spec_1),
&HeapCellValue::Integer(ref n2), &HeapCellValue::Atom(ref n2, ref spec_2),
) => { ) => {
if n1 != n2 { if n1 != n2 || spec_1 != spec_2 {
return true;
}
}
(
&HeapCellValue::Rational(ref n1),
&HeapCellValue::Rational(ref n2),
) => {
if n1 != n2 {
return true; return true;
} }
} }
@@ -1828,14 +1802,17 @@ impl MachineState {
} }
} }
( (
&HeapCellValue::Atom(ref n1, ref spec_1), v1,
&HeapCellValue::Atom(ref n2, ref spec_2), v2,
) => { ) => {
if n1 != n2 || spec_1 != spec_2 { if let Ok(n1) = Number::try_from(v1) {
return true; if let Ok(n2) = Number::try_from(v2) {
if n1 == n2 {
continue;
}
}
} }
}
_ => {
return true; return true;
} }
} }
@@ -1852,25 +1829,26 @@ impl MachineState {
} }
} }
} }
(Addr::Usize(n1), Addr::Con(n2)) | (Addr::Con(n2), Addr::Usize(n1)) => { (Addr::CharCode(n1), v2) | (v2, Addr::CharCode(n1)) => {
if let HeapCellValue::Integer(ref n2) = &self.heap[n2] { if let Ok(n2) = Number::try_from((v2, &self.heap)) {
if let Some(n2) = n2.to_usize() { if let Some(n2) = n2.to_u32() {
if n1 != n2 { if n1 != n2 {
return true; return true;
} }
} }
} }
} }
(Addr::CharCode(n1), Addr::Con(n2)) | (Addr::Con(n2), Addr::CharCode(n1)) => { (a1, a2) => {
if let HeapCellValue::Integer(ref n2) = &self.heap[n2] { if let Ok(n1) = Number::try_from((a1, &self.heap)) {
if let Some(n2) = n2.to_u32() { if let Ok(n2) = Number::try_from((a2, &self.heap)) {
if n1 == n2 { if n1 != n2 {
return true; return true;
} else {
continue;
} }
} }
} }
}
(a1, a2) => {
if a1 != a2 { if a1 != a2 {
return true; return true;
} }
@@ -1919,74 +1897,62 @@ impl MachineState {
Addr::Con(h1), Addr::Con(h1),
Addr::Con(h2), Addr::Con(h2),
) => { ) => {
match (&self.heap[h1], &self.heap[h2]) { if let Ok(n1) = Number::try_from(&self.heap[h1]) {
( if let Ok(n2) = Number::try_from(&self.heap[h2]) {
HeapCellValue::Integer(ref n1), if n1 != n2 {
HeapCellValue::Integer(ref n2), return Some(n1.cmp(&n2));
) => {
if &*n1 != &*n2 {
return Some(n1.cmp(&*n2));
} }
} } else {
(
HeapCellValue::Rational(ref n1),
HeapCellValue::Integer(ref n2),
) => {
if &**n1 != &**n2 {
return n1.as_ref().partial_cmp(n2.as_ref());
}
}
(
HeapCellValue::Integer(ref n1),
HeapCellValue::Rational(ref n2),
) => {
if &**n1 != &**n2 {
return n1.as_ref().partial_cmp(n2.as_ref());
}
}
(
HeapCellValue::Rational(ref r1),
HeapCellValue::Rational(ref r2),
) => {
if &*r1 != &*r2 {
return Some(r1.cmp(r2));
}
}
_ => {
unreachable!() unreachable!()
} }
} else {
unreachable!()
} }
} }
(Addr::Usize(n1), Addr::Usize(n2)) => { (
if n1 != n2 { Addr::Con(h1),
return Some(n1.cmp(&n2)); v2,
} ) => {
} if let Ok(n1) = Number::try_from(&self.heap[h1]) {
(Addr::CharCode(n1), Addr::CharCode(n2)) => { if let Ok(n2) = Number::try_from(&HeapCellValue::Addr(v2)) {
if n1 != n2 {
return Some(n1.cmp(&n2));
}
}
(Addr::Usize(n1), Addr::Con(n2)) | (Addr::Con(n2), Addr::Usize(n1)) => {
if let HeapCellValue::Integer(ref n2) = &self.heap[n2] {
if let Some(n2) = n2.to_usize() {
if n1 != n2 { if n1 != n2 {
return Some(n1.cmp(&n2)); return Some(n1.cmp(&n2));
} }
} else {
unreachable!()
} }
} else {
unreachable!()
} }
} }
(Addr::CharCode(n1), Addr::Con(n2)) | (Addr::Con(n2), Addr::CharCode(n1)) => { (
if let HeapCellValue::Integer(ref n2) = &self.heap[n2] { v1,
if let Some(n2) = n2.to_u32() { Addr::Con(h2),
) => {
if let Ok(n1) = Number::try_from(&HeapCellValue::Addr(v1)) {
if let Ok(n2) = Number::try_from(&self.heap[h2]) {
if n1 != n2 { if n1 != n2 {
return Some(n1.cmp(&n2)); return Some(n1.cmp(&n2));
} }
} else {
unreachable!()
} }
} else {
unreachable!()
} }
} }
_ => { (v1, v2) => {
unreachable!() if let Ok(n1) = Number::try_from(&HeapCellValue::Addr(v1)) {
if let Ok(n2) = Number::try_from(&HeapCellValue::Addr(v2)) {
if n1 != n2 {
return Some(n1.cmp(&n2));
}
} else {
unreachable!()
}
} else {
unreachable!()
}
} }
} }
} }
@@ -2330,34 +2296,34 @@ impl MachineState {
&InlinedClauseType::IsInteger(r1) => { &InlinedClauseType::IsInteger(r1) => {
let d = self.store(self.deref(self[r1])); let d = self.store(self.deref(self[r1]));
match d { match Number::try_from((d, &self.heap)) {
Addr::Con(h) => { Ok(Number::Fixnum(_)) => {
match &self.heap[h] { self.p += 1;
HeapCellValue::Integer(_) => { }
Ok(Number::Integer(_)) => {
self.p += 1;
}
Ok(Number::Rational(n)) => {
if n.denom() == &1 {
self.p += 1;
} else {
self.fail = true;
}
}
_ => {
match d {
Addr::CharCode(_) => {
self.p += 1; self.p += 1;
} }
HeapCellValue::Rational(ref r) => { Addr::Char(_) if self.flags.double_quotes.is_codes() => {
if r.denom() == &1 { self.p += 1;
self.p += 1;
} else {
self.fail = true;
}
} }
_ => { _ => {
self.fail = true; self.fail = true;
} }
} }
} }
Addr::CharCode(_) | Addr::Usize(_) => { }
self.p += 1;
}
Addr::Char(_) if self.flags.double_quotes.is_codes() => {
self.p += 1;
}
_ => {
self.fail = true;
}
};
} }
&InlinedClauseType::IsCompound(r1) => { &InlinedClauseType::IsCompound(r1) => {
let d = self.store(self.deref(self[r1])); let d = self.store(self.deref(self[r1]));
@@ -2484,8 +2450,8 @@ impl MachineState {
Addr::Stream(_) => { Addr::Stream(_) => {
self.fail = true; self.fail = true;
} }
Addr::Char(_) | Addr::CharCode(_) | Addr::Con(_) | Addr::Float(_) | Addr::Char(_) | Addr::CharCode(_) | Addr::Con(_) | Addr::Fixnum(_) |
Addr::EmptyList | Addr::Usize(_) => { Addr::Float(_) | Addr::EmptyList | Addr::Usize(_) => {
self.try_functor_unify_components(a1, 0); self.try_functor_unify_components(a1, 0);
} }
Addr::Str(o) => match self.heap.clone(o) { Addr::Str(o) => match self.heap.clone(o) {
@@ -2510,48 +2476,33 @@ impl MachineState {
return Err(self.error_form(MachineError::instantiation_error(), stub)); return Err(self.error_form(MachineError::instantiation_error(), stub));
} }
let arity = match arity { let arity =
Addr::Con(h) => { match Number::try_from((arity, &self.heap)) {
match &self.heap[h] { Ok(Number::Fixnum(n)) => Some(n),
&HeapCellValue::Integer(ref n) => { Ok(Number::Integer(n)) => n.to_isize(),
n.to_isize() Ok(Number::Rational(n))
if n.denom() == &1 => {
n.numer().to_isize()
},
_ =>
match arity {
Addr::CharCode(c) => {
Some(c as isize)
}
arity => {
return Err(
self.error_form(
MachineError::type_error(
self.heap.h(),
ValidType::Integer,
arity,
),
stub,
)
);
}
} }
&HeapCellValue::Addr(Addr::Usize(n)) => { };
Some(n as isize)
}
_ => {
return Err(
self.error_form(
MachineError::type_error(
self.heap.h(),
ValidType::Integer,
arity,
),
stub,
)
);
}
}
},
Addr::Usize(n) => {
Some(n as isize)
}
Addr::CharCode(c) => {
Some(c as isize)
}
arity => {
return Err(
self.error_form(
MachineError::type_error(
self.heap.h(),
ValidType::Integer,
arity,
),
stub,
)
);
}
};
let arity = match arity { let arity = match arity {
Some(arity) => { Some(arity) => {
@@ -2579,7 +2530,7 @@ impl MachineState {
} }
match name { match name {
Addr::Char(_) | Addr::CharCode(_) | Addr::Con(_) | Addr::Float(_) | Addr::Char(_) | Addr::CharCode(_) | Addr::Con(_) | Addr::Fixnum(_) | Addr::Float(_) |
Addr::EmptyList | Addr::PStrLocation(..) | Addr::Usize(_) if arity == 0 => { Addr::EmptyList | Addr::PStrLocation(..) | Addr::Usize(_) if arity == 0 => {
self.unify(a1, name); self.unify(a1, name);
} }
@@ -2925,34 +2876,6 @@ impl MachineState {
HeapCellValue::Addr(Addr::PStrLocation(..)), HeapCellValue::Addr(Addr::PStrLocation(..)),
) => { ) => {
} }
(
HeapCellValue::Integer(n1),
HeapCellValue::Integer(n2),
) => {
if &*n1 != &*n2 {
return true;
}
}
(
HeapCellValue::Rational(n1),
HeapCellValue::Rational(n2),
) => {
if &*n1 != &*n2 {
return true;
}
}
(
HeapCellValue::Integer(ref n1),
HeapCellValue::Rational(ref n2),
) |
(
HeapCellValue::Rational(ref n2),
HeapCellValue::Integer(ref n1),
) => {
if n1.as_ref().partial_cmp(&**n2) == Some(Ordering::Equal) {
return true;
}
}
( (
HeapCellValue::Atom(ref n1, ref spec_1), HeapCellValue::Atom(ref n1, ref spec_1),
HeapCellValue::Atom(ref n2, ref spec_2), HeapCellValue::Atom(ref n2, ref spec_2),
@@ -2970,15 +2893,34 @@ impl MachineState {
} }
} }
( (
HeapCellValue::Addr(a1), v1,
HeapCellValue::Addr(a2), v2,
) => { ) => {
if a1 != a2 { if let Ok(n1) = Number::try_from(v1) {
return true; if let Ok(n2) = Number::try_from(v2) {
if n1 != n2 {
return true;
} else {
continue;
}
} else {
return true;
}
}
match (v1, v2) {
(
HeapCellValue::Addr(a1),
HeapCellValue::Addr(a2),
) => {
if a1 != a2 {
return true;
}
}
_ => {
return true;
}
} }
}
_ => {
return true;
} }
} }
} }
@@ -3051,13 +2993,13 @@ impl MachineState {
lco: bool, lco: bool,
use_default_cp: bool, use_default_cp: bool,
) { ) {
let interrupted = INTERRUPT.load(std::sync::atomic::Ordering::Relaxed); let interrupted = INTERRUPT.load(std::sync::atomic::Ordering::Relaxed);
if INTERRUPT.compare_and_swap(interrupted, false, std::sync::atomic::Ordering::Relaxed) { if INTERRUPT.compare_and_swap(interrupted, false, std::sync::atomic::Ordering::Relaxed) {
self.reset(); self.reset();
self.fail = true; self.fail = true;
return; return;
} }
let mut default_call_policy: Box<dyn CallPolicy> = Box::new(DefaultCallPolicy {}); let mut default_call_policy: Box<dyn CallPolicy> = Box::new(DefaultCallPolicy {});
@@ -3192,8 +3134,12 @@ impl MachineState {
self.hb = self.heap.h(); self.hb = self.heap.h();
self.p += offset; self.p += offset;
} }
&IndexedChoiceInstruction::Retry(l) => try_or_fail!(self, call_policy.retry(self, l)), &IndexedChoiceInstruction::Retry(l) => {
&IndexedChoiceInstruction::Trust(l) => try_or_fail!(self, call_policy.trust(self, l)), try_or_fail!(self, call_policy.retry(self, l));
}
&IndexedChoiceInstruction::Trust(l) => {
try_or_fail!(self, call_policy.trust(self, l));
}
}; };
} }
@@ -3241,7 +3187,9 @@ impl MachineState {
&ChoiceInstruction::RetryMeElse(offset) => { &ChoiceInstruction::RetryMeElse(offset) => {
try_or_fail!(self, call_policy.retry_me_else(self, offset)) try_or_fail!(self, call_policy.retry_me_else(self, offset))
} }
&ChoiceInstruction::TrustMe => try_or_fail!(self, call_policy.trust_me(self)), &ChoiceInstruction::TrustMe => {
try_or_fail!(self, call_policy.trust_me(self))
}
} }
} }

View File

@@ -45,6 +45,7 @@ use crate::prolog::machine::toplevel::*;
use indexmap::IndexMap; use indexmap::IndexMap;
use std::collections::VecDeque; use std::collections::VecDeque;
use std::convert::TryFrom;
use std::fs::File; use std::fs::File;
use std::mem; use std::mem;
use std::ops::Index; use std::ops::Index;
@@ -205,11 +206,11 @@ impl SubModuleUser for IndexStore {
#[inline] #[inline]
fn current_dir() -> std::path::PathBuf { fn current_dir() -> std::path::PathBuf {
let mut path_buf = std::path::PathBuf::from(PROJECT_DIR); let mut path_buf = std::path::PathBuf::from(PROJECT_DIR);
// file!() always produces a path relative to PROJECT_DIR. // file!() always produces a path relative to PROJECT_DIR.
path_buf = path_buf.join(std::path::PathBuf::from(file!())); path_buf = path_buf.join(std::path::PathBuf::from(file!()));
path_buf.pop(); path_buf.pop();
path_buf path_buf
} }
@@ -322,34 +323,34 @@ impl Machine {
} }
pub fn run_init_code(&mut self, code: Code) -> bool { pub fn run_init_code(&mut self, code: Code) -> bool {
let old_machine_st = self.sink_to_snapshot(); let old_machine_st = self.sink_to_snapshot();
self.machine_st.reset(); self.machine_st.reset();
self.code_repo.cached_query = code; self.code_repo.cached_query = code;
self.run_query(); self.run_query();
let result = self.machine_st.fail; let result = self.machine_st.fail;
self.absorb_snapshot(old_machine_st); self.absorb_snapshot(old_machine_st);
!result !result
} }
pub fn run_top_level(&mut self) { pub fn run_top_level(&mut self) {
use std::env; use std::env;
let mut filename_atoms = vec![]; let mut filename_atoms = vec![];
// the first of these is the path to the scryer-prolog executable, so skip // 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 = clause_name!(filename, self.indices.atom_tbl); let atom = clause_name!(filename, self.indices.atom_tbl);
filename_atoms.push(HeapCellValue::Atom(atom, None)); filename_atoms.push(HeapCellValue::Atom(atom, None));
} }
let list_addr = let list_addr =
Addr::HeapCell(self.machine_st.heap.to_list(filename_atoms.into_iter())); Addr::HeapCell(self.machine_st.heap.to_list(filename_atoms.into_iter()));
self.machine_st[temp_v!(1)] = list_addr; self.machine_st[temp_v!(1)] = list_addr;
self.machine_st.p = CodePtr::Local(LocalCodePtr::DirEntry(self.toplevel_idx)); self.machine_st.p = CodePtr::Local(LocalCodePtr::DirEntry(self.toplevel_idx));
self.run_query(); self.run_query();
@@ -397,7 +398,7 @@ impl Machine {
lib_path.clone(), lib_path.clone(),
) )
); );
compile_user_module(&mut wam, compile_user_module(&mut wam,
Stream::from(LISTS), Stream::from(LISTS),
true, true,
@@ -406,7 +407,7 @@ impl Machine {
lib_path.clone(), lib_path.clone(),
), ),
); );
compile_user_module(&mut wam, compile_user_module(&mut wam,
Stream::from(ISO_EXT), Stream::from(ISO_EXT),
true, true,
@@ -415,7 +416,7 @@ impl Machine {
lib_path.clone(), lib_path.clone(),
) )
); );
compile_user_module(&mut wam, compile_user_module(&mut wam,
Stream::from(SI), Stream::from(SI),
true, true,
@@ -539,53 +540,57 @@ impl Machine {
fn extract_module_export_list(&mut self) -> Result<Vec<ModuleExport>, ParserError> fn extract_module_export_list(&mut self) -> Result<Vec<ModuleExport>, ParserError>
{ {
let mut export_list = self.machine_st[temp_v!(2)].clone(); let mut export_list = self.machine_st[temp_v!(2)].clone();
let mut exports = vec![]; let mut exports = vec![];
while let Addr::Lis(l) = self.machine_st.store(self.machine_st.deref(export_list)) { while let Addr::Lis(l) = self.machine_st.store(self.machine_st.deref(export_list)) {
match &self.machine_st.heap[l] { match &self.machine_st.heap[l] {
&HeapCellValue::Addr(Addr::Str(s)) => { &HeapCellValue::Addr(Addr::Str(s)) => {
match &self.machine_st.heap[s] { match &self.machine_st.heap[s] {
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::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::Integer(ref arity) => &HeapCellValue::Integer(ref arity) =>
arity.to_usize().unwrap(), arity.to_usize().unwrap(),
_ => &HeapCellValue::Addr(Addr::Fixnum(n)) =>
unreachable!() usize::try_from(n).unwrap(),
}; _ =>
unreachable!()
};
exports.push(ModuleExport::PredicateKey((name, arity))); exports.push(ModuleExport::PredicateKey((name, arity)));
} }
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::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::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::Integer(ref arity) => &HeapCellValue::Integer(ref arity) =>
arity.to_usize().unwrap(), arity.to_usize().unwrap(),
_ => &HeapCellValue::Addr(Addr::Fixnum(n)) =>
unreachable!() usize::try_from(n).unwrap(),
}; _ =>
unreachable!()
};
exports.push(ModuleExport::OpDecl(to_op_decl( exports.push(ModuleExport::OpDecl(to_op_decl(
prec, prec,
@@ -595,47 +600,47 @@ impl Machine {
} }
_ => unreachable!() _ => unreachable!()
} }
} }
_ => unreachable!() _ => unreachable!()
}
export_list = self.machine_st.heap[l+1].as_addr(l+1);
} }
export_list = self.machine_st.heap[l+1].as_addr(l+1); Ok(exports)
}
Ok(exports)
} }
fn use_module<ToSource>(&mut self, to_src: ToSource) fn use_module<ToSource>(&mut self, to_src: ToSource)
where ToSource: Fn(ClauseName) -> ModuleSource where ToSource: Fn(ClauseName) -> ModuleSource
{ {
// the term expander will overwrite the cached query, so save it here. // the term expander will overwrite the cached query, so save it here.
let cached_query = mem::replace(&mut self.code_repo.cached_query, vec![]); let 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 = { let name = {
let addr = self.machine_st.store(self.machine_st.deref(module_spec)); let addr = self.machine_st.store(self.machine_st.deref(module_spec));
match self.machine_st.heap.index_addr(&addr).as_ref() { match self.machine_st.heap.index_addr(&addr).as_ref() {
HeapCellValue::Atom(name, _) => name.clone(), HeapCellValue::Atom(name, _) => name.clone(),
_ => unreachable!(), _ => unreachable!(),
} }
}; };
let load_result = match to_src(name) { let load_result = match to_src(name) {
ModuleSource::Library(name) => ModuleSource::Library(name) =>
if let Some(module) = self.indices.take_module(name.clone()) { if let Some(module) = self.indices.take_module(name.clone()) {
self.indices.remove_module(clause_name!("user"), &module); self.indices.remove_module(clause_name!("user"), &module);
self.indices.modules.insert(name.clone(), module); self.indices.modules.insert(name.clone(), module);
Ok(name) Ok(name)
} else { } else {
load_library(self, name, false) load_library(self, name, false)
}, },
ModuleSource::File(name) => ModuleSource::File(name) =>
load_module_from_file(self, PathBuf::from(name.as_str()), false) load_module_from_file(self, PathBuf::from(name.as_str()), false)
}; };
let result = load_result.and_then(|name| { let result = load_result.and_then(|name| {
let module = self.indices.take_module(name.clone()).unwrap(); let module = self.indices.take_module(name.clone()).unwrap();
if !module.is_impromptu_module { if !module.is_impromptu_module {
@@ -645,30 +650,30 @@ impl Machine {
Ok(self.indices.insert_module(module)) Ok(self.indices.insert_module(module))
}); });
self.code_repo.cached_query = cached_query; self.code_repo.cached_query = cached_query;
if let Err(e) = result { if let Err(e) = result {
self.throw_session_error(e, (clause_name!("use_module"), 1)); self.throw_session_error(e, (clause_name!("use_module"), 1));
} }
} }
fn use_qualified_module<ToSource>(&mut self, to_src: ToSource) fn use_qualified_module<ToSource>(&mut self, to_src: ToSource)
where ToSource: Fn(ClauseName) -> ModuleSource where ToSource: Fn(ClauseName) -> ModuleSource
{ {
// the term expander will overwrite the cached query, so save it here. // the term expander will overwrite the cached query, so save it here.
let cached_query = mem::replace(&mut self.code_repo.cached_query, vec![]); let 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 = { let name = {
let addr = self.machine_st.store(self.machine_st.deref(module_spec)); let addr = self.machine_st.store(self.machine_st.deref(module_spec));
match self.machine_st.heap.index_addr(&addr).as_ref() { match self.machine_st.heap.index_addr(&addr).as_ref() {
HeapCellValue::Atom(name, _) => name.clone(), HeapCellValue::Atom(name, _) => name.clone(),
_ => unreachable!(), _ => unreachable!(),
} }
}; };
let exports = match self.extract_module_export_list() { let exports = match self.extract_module_export_list() {
Ok(exports) => exports, Ok(exports) => exports,
Err(e) => { Err(e) => {
self.throw_session_error(SessionError::from(e), (clause_name!("use_module"), 2)); self.throw_session_error(SessionError::from(e), (clause_name!("use_module"), 2));
@@ -676,38 +681,38 @@ impl Machine {
} }
}; };
let load_result = match to_src(name) { let load_result = match to_src(name) {
ModuleSource::Library(name) => ModuleSource::Library(name) =>
if let Some(module) = self.indices.take_module(name.clone()) { if let Some(module) = self.indices.take_module(name.clone()) {
self.indices.remove_module(clause_name!("user"), &module); self.indices.remove_module(clause_name!("user"), &module);
self.indices.modules.insert(name.clone(), module); self.indices.modules.insert(name.clone(), module);
Ok(name) Ok(name)
} else { } else {
load_library(self, name, false) load_library(self, name, false)
}, },
ModuleSource::File(name) => ModuleSource::File(name) =>
load_module_from_file(self, PathBuf::from(name.as_str()), false) load_module_from_file(self, PathBuf::from(name.as_str()), false)
}; };
let result = load_result.and_then(|name| { let result = load_result.and_then(|name| {
let module = self.indices.take_module(name.clone()).unwrap(); let module = self.indices.take_module(name.clone()).unwrap();
if !module.is_impromptu_module { if !module.is_impromptu_module {
self.indices.use_qualified_module(&mut self.code_repo, self.indices.use_qualified_module(&mut self.code_repo,
self.machine_st.flags, self.machine_st.flags,
&module, &module,
&exports)?; &exports)?;
} }
Ok(self.indices.insert_module(module)) Ok(self.indices.insert_module(module))
}); });
self.code_repo.cached_query = cached_query; self.code_repo.cached_query = cached_query;
if let Err(e) = result { if let Err(e) = result {
self.throw_session_error(e, (clause_name!("use_module"), 2)); self.throw_session_error(e, (clause_name!("use_module"), 2));
} }
} }
fn handle_toplevel_command(&mut self, code_ptr: REPLCodePtr, p: LocalCodePtr) { fn handle_toplevel_command(&mut self, code_ptr: REPLCodePtr, p: LocalCodePtr) {
@@ -722,14 +727,14 @@ impl Machine {
self.throw_session_error(e, (clause_name!("repl"), 0)); self.throw_session_error(e, (clause_name!("repl"), 0));
} }
} }
REPLCodePtr::UseModule => REPLCodePtr::UseModule =>
self.use_module(ModuleSource::Library), self.use_module(ModuleSource::Library),
REPLCodePtr::UseModuleFromFile => REPLCodePtr::UseModuleFromFile =>
self.use_module(ModuleSource::File), self.use_module(ModuleSource::File),
REPLCodePtr::UseQualifiedModule => REPLCodePtr::UseQualifiedModule =>
self.use_qualified_module(ModuleSource::Library), self.use_qualified_module(ModuleSource::Library),
REPLCodePtr::UseQualifiedModuleFromFile => REPLCodePtr::UseQualifiedModuleFromFile =>
self.use_qualified_module(ModuleSource::File) self.use_qualified_module(ModuleSource::File)
} }
self.machine_st.p = CodePtr::Local(p); self.machine_st.p = CodePtr::Local(p);
@@ -786,7 +791,7 @@ impl Machine {
} }
pub(super) fn run_query(&mut self) { pub(super) fn run_query(&mut self) {
self.machine_st.cp = LocalCodePtr::TopLevel(0, self.code_repo.size_of_cached_query()); self.machine_st.cp = LocalCodePtr::TopLevel(0, self.code_repo.size_of_cached_query());
let end_ptr = CodePtr::Local(self.machine_st.cp); let end_ptr = CodePtr::Local(self.machine_st.cp);
while self.machine_st.p < end_ptr { while self.machine_st.p < end_ptr {

View File

@@ -23,9 +23,9 @@ use crate::ref_thread_local::RefThreadLocal;
use indexmap::{IndexMap, IndexSet}; use indexmap::{IndexMap, IndexSet};
use std::cmp; use std::cmp;
use std::convert::TryFrom;
use std::io::{stdout, Write}; use std::io::{stdout, Write};
use std::iter::once; use std::iter::once;
use std::mem;
use std::rc::Rc; use std::rc::Rc;
use crate::crossterm::event::{read, Event, KeyCode, KeyEvent}; use crate::crossterm::event::{read, Event, KeyCode, KeyEvent};
@@ -269,9 +269,9 @@ impl MachineState {
} }
} }
fn skip_max_list_result(&mut self, max_steps: &Integer) { fn skip_max_list_result(&mut self, max_steps: Option<isize>) {
let search_result = let search_result =
if let Some(max_steps) = max_steps.to_isize() { if let Some(max_steps) = max_steps {
if max_steps == -1 { if max_steps == -1 {
self.detect_cycles(self[temp_v!(3)]) self.detect_cycles(self[temp_v!(3)])
} else { } else {
@@ -307,59 +307,66 @@ impl MachineState {
}; };
} }
pub(super) fn skip_max_list(&mut self) -> CallResult { pub(super)
fn skip_max_list(&mut self) -> CallResult {
let max_steps = self.store(self.deref(self[temp_v!(2)])); let max_steps = self.store(self.deref(self[temp_v!(2)]));
match max_steps { match max_steps {
Addr::Con(h) if self.heap.integer_at(h) => { Addr::HeapCell(_) | Addr::StackCell(..) | Addr::AttrVar(_) => {
if let HeapCellValue::Integer(ref max_steps) = self.heap.clone(h) {
if max_steps.to_isize().map(|i| i >= -1).unwrap_or(false) {
let n = self.store(self.deref(self[temp_v!(1)]));
match n {
Addr::Con(h) if self.heap.integer_at(h) => {
if let HeapCellValue::Integer(ref n) = &self.heap[h] {
if n.as_ref() == &0 {
let xs0 = self[temp_v!(3)];
let xs = self[temp_v!(4)];
self.unify(xs0, xs);
} else {
self.skip_max_list_result(max_steps.as_ref());
}
} else {
unreachable!()
}
}
_ => {
self.skip_max_list_result(max_steps.as_ref());
}
}
} else {
self.fail = true;
}
} else {
unreachable!()
}
}
Addr::HeapCell(_) | Addr::StackCell(..) => {
let stub = MachineError::functor_stub(clause_name!("$skip_max_list"), 4); let stub = MachineError::functor_stub(clause_name!("$skip_max_list"), 4);
return Err(self.error_form(MachineError::instantiation_error(), stub)); return Err(self.error_form(MachineError::instantiation_error(), stub));
} }
addr => { addr => {
let stub = MachineError::functor_stub(clause_name!("$skip_max_list"), 4); let max_steps_n =
return Err( match Number::try_from((max_steps, &self.heap)) {
self.error_form( Ok(Number::Integer(n)) => n.to_isize(),
MachineError::type_error( Ok(Number::Fixnum(n)) => Some(n),
self.heap.h(), _ => None,
ValidType::Integer, };
addr
), if max_steps_n.map(|i| i >= -1).unwrap_or(false) {
stub, let n = self.store(self.deref(self[temp_v!(1)]));
)
); match Number::try_from((n, &self.heap)) {
Ok(Number::Integer(n)) => {
if n.as_ref() == &0 {
let xs0 = self[temp_v!(3)];
let xs = self[temp_v!(4)];
self.unify(xs0, xs);
} else {
self.skip_max_list_result(max_steps_n);
}
}
Ok(Number::Fixnum(n)) => {
if n == 0 {
let xs0 = self[temp_v!(3)];
let xs = self[temp_v!(4)];
self.unify(xs0, xs);
} else {
self.skip_max_list_result(max_steps_n);
}
}
_ => {
self.skip_max_list_result(max_steps_n);
}
}
} else {
let stub = MachineError::functor_stub(clause_name!("$skip_max_list"), 4);
return Err(
self.error_form(
MachineError::type_error(
self.heap.h(),
ValidType::Integer,
addr
),
stub,
)
);
}
} }
}; }
Ok(()) Ok(())
} }
@@ -671,6 +678,10 @@ impl MachineState {
let addr = self.heap.put_constant(Constant::Integer(n)); let addr = self.heap.put_constant(Constant::Integer(n));
self.unify(nx, addr); self.unify(nx, addr);
} }
Ok(Term::Constant(_, Constant::Fixnum(n))) => {
let addr = self.heap.put_constant(Constant::Fixnum(n));
self.unify(nx, addr);
}
Ok(Term::Constant(_, Constant::CharCode(c))) => { Ok(Term::Constant(_, Constant::CharCode(c))) => {
self.unify(nx, Addr::CharCode(c)) self.unify(nx, Addr::CharCode(c))
} }
@@ -774,17 +785,18 @@ impl MachineState {
} }
&SystemClauseType::BindFromRegister => { &SystemClauseType::BindFromRegister => {
let reg = self.store(self.deref(self[temp_v!(2)])); let reg = self.store(self.deref(self[temp_v!(2)]));
let n = match reg { let n =
Addr::Con(h) => match Number::try_from((reg, &self.heap)) {
if let HeapCellValue::Integer(ref n) = &self.heap[h] { Ok(Number::Integer(n)) => {
n.to_usize() n.to_usize()
} else { }
Ok(Number::Fixnum(n)) => {
usize::try_from(n).ok()
}
_ => {
unreachable!() unreachable!()
} }
_ => { };
unreachable!()
}
};
if let Some(n) = n { if let Some(n) = n {
if n <= MAX_ARITY { if n <= MAX_ARITY {
@@ -1020,15 +1032,36 @@ impl MachineState {
let mut chars = String::new(); let mut chars = String::new();
for addr in addrs { for addr in addrs {
match addr { match Number::try_from((addr, &self.heap)) {
Addr::Con(h) if self.heap.integer_at(h) => { Ok(Number::Fixnum(n)) => {
if let HeapCellValue::Integer(ref n) = &self.heap[h] { match u32::try_from(n) {
let c = self.int_to_char_code(&n, "atom_codes", 2)?; Ok(c) => {
chars.push(std::char::from_u32(c).unwrap()); chars.push(std::char::from_u32(c).unwrap());
} else { }
unreachable!() _ => {
let c = self.int_to_char_code(
&Integer::from(n),
"atom_codes",
2,
)?;
chars.push(std::char::from_u32(c).unwrap());
}
} }
continue;
} }
Ok(Number::Integer(n)) => {
let c = self.int_to_char_code(&n, "atom_codes", 2)?;
chars.push(std::char::from_u32(c).unwrap());
continue;
}
_ => {
}
}
match addr {
Addr::CharCode(c) => { Addr::CharCode(c) => {
chars.push(std::char::from_u32(c).unwrap()); chars.push(std::char::from_u32(c).unwrap());
} }
@@ -1056,7 +1089,9 @@ impl MachineState {
} }
} }
} }
_ => unreachable!(), _ => {
unreachable!()
}
}; };
} }
&SystemClauseType::AtomLength => { &SystemClauseType::AtomLength => {
@@ -1088,17 +1123,6 @@ impl MachineState {
self.unify(a2, len); self.unify(a2, len);
} }
&SystemClauseType::CallAttributeGoals => {
let p = self.attr_var_init.project_attrs_loc;
if self.last_call {
self.execute_at_index(2, dir_entry!(p));
} else {
self.call_at_index(2, dir_entry!(p));
}
return Ok(());
}
&SystemClauseType::CallContinuation => { &SystemClauseType::CallContinuation => {
let stub = MachineError::functor_stub(clause_name!("call_continuation"), 1); let stub = MachineError::functor_stub(clause_name!("call_continuation"), 1);
@@ -1201,21 +1225,23 @@ impl MachineState {
let n = self[temp_v!(1)]; let n = self[temp_v!(1)];
let chs = self[temp_v!(2)]; let chs = self[temp_v!(2)];
let string = match self.store(self.deref(n)) { let n = self.store(self.deref(n));
Addr::Float(OrderedFloat(n)) => {
format!("{0:<20?}", n) let string =
} match Number::try_from((n, &self.heap)) {
Addr::Con(h) if self.heap.integer_at(h) => { Ok(Number::Float(OrderedFloat(n))) => {
if let HeapCellValue::Integer(ref n) = &self.heap[h] { format!("{0:<20?}", n)
}
Ok(Number::Fixnum(n)) => {
n.to_string() n.to_string()
} else { }
Ok(Number::Integer(n)) => {
n.to_string()
}
_ => {
unreachable!() unreachable!()
} }
} };
_ => {
unreachable!()
}
};
let chars = string.trim().chars().map(|c| Addr::Char(c)); let chars = string.trim().chars().map(|c| Addr::Char(c));
let char_list = Addr::HeapCell(self.heap.to_list(chars)); let char_list = Addr::HeapCell(self.heap.to_list(chars));
@@ -1226,21 +1252,21 @@ impl MachineState {
let n = self[temp_v!(1)]; let n = self[temp_v!(1)];
let chs = self[temp_v!(2)]; let chs = self[temp_v!(2)];
let string = match self.store(self.deref(n)) { let string =
Addr::Float(OrderedFloat(n)) => { match Number::try_from((n, &self.heap)) {
format!("{0:<20?}", n) Ok(Number::Float(OrderedFloat(n))) => {
} format!("{0:<20?}", n)
Addr::Con(h) if self.heap.integer_at(h) => { }
if let HeapCellValue::Integer(ref n) = &self.heap[h] { Ok(Number::Fixnum(n)) => {
n.to_string() n.to_string()
} else { }
Ok(Number::Integer(n)) => {
n.to_string()
}
_ => {
unreachable!() unreachable!()
} }
} };
_ => {
unreachable!()
}
};
let codes = string let codes = string
.trim() .trim()
@@ -1322,33 +1348,37 @@ impl MachineState {
} }
addr if addr.is_ref() => { addr if addr.is_ref() => {
let a2 = self[temp_v!(2)]; let a2 = self[temp_v!(2)];
let a2 = self.store(self.deref(a2));
match self.store(self.deref(a2)) { let c = match Number::try_from((a2, &self.heap)) {
Addr::CharCode(code) => { Ok(Number::Integer(n)) => {
if let Some(c) = std::char::from_u32(code) { self.int_to_char_code(&n, "char_code", 2)?
self.unify(Addr::Char(c), addr); }
} else { Ok(Number::Fixnum(n)) => {
self.fail = true; self.int_to_char_code(&Integer::from(n), "char_code", 2)?
}
_ => {
match addr {
Addr::CharCode(c) => {
c
}
_ => {
self.fail = true;
return Ok(());
}
} }
} }
Addr::Con(h) if self.heap.integer_at(h) => {
let c =
if let HeapCellValue::Integer(n) = &self.heap[h] {
self.int_to_char_code(&n, "char_code", 2)?
} else {
unreachable!()
};
if let Some(c) = std::char::from_u32(c) {
self.unify(Addr::Char(c), addr);
} else {
self.fail = true;
}
}
_ => self.fail = true,
}; };
if let Some(c) = std::char::from_u32(c) {
self.unify(Addr::Char(c), addr);
} else {
self.fail = true;
}
}
_ => {
unreachable!();
} }
_ => unreachable!(),
}; };
} }
&SystemClauseType::CheckCutPoint => { &SystemClauseType::CheckCutPoint => {
@@ -1967,16 +1997,20 @@ impl MachineState {
let specifier = self[temp_v!(2)]; let specifier = self[temp_v!(2)];
let op = self[temp_v!(3)]; let op = self[temp_v!(3)];
let priority = match self.store(self.deref(priority)) { let priority = self.store(self.deref(priority));
Addr::Con(h) if self.heap.integer_at(h) =>
if let HeapCellValue::Integer(ref n) = &self.heap[h] { let priority =
match Number::try_from((priority, &self.heap)) {
Ok(Number::Integer(n)) => {
n.to_usize().unwrap() n.to_usize().unwrap()
} else { }
unreachable!() Ok(Number::Fixnum(n)) => {
}, usize::try_from(n).unwrap()
_ => }
unreachable!(), _ => {
}; unreachable!();
}
};
let specifier = match self.store(self.deref(specifier)) { let specifier = match self.store(self.deref(specifier)) {
Addr::Con(h) if self.heap.atom_at(h) => Addr::Con(h) if self.heap.atom_at(h) =>
@@ -2041,10 +2075,6 @@ impl MachineState {
let attr_goals = self.attr_var_init.attribute_goals.clone(); let attr_goals = self.attr_var_init.attribute_goals.clone();
self.fetch_attribute_goals(attr_goals); self.fetch_attribute_goals(attr_goals);
} }
&SystemClauseType::FetchAttributeGoals => {
let attr_goals = mem::replace(&mut self.attr_var_init.attribute_goals, vec![]);
self.fetch_attribute_goals(attr_goals);
}
&SystemClauseType::GetAttributedVariableList => { &SystemClauseType::GetAttributedVariableList => {
let attr_var = self.store(self.deref(self[temp_v!(1)])); let attr_var = self.store(self.deref(self[temp_v!(1)]));
let attr_var_list = let attr_var_list =
@@ -2080,35 +2110,36 @@ impl MachineState {
} }
&SystemClauseType::GetAttrVarQueueBeyond => { &SystemClauseType::GetAttrVarQueueBeyond => {
let addr = self[temp_v!(1)]; let addr = self[temp_v!(1)];
let addr = self.store(self.deref(addr));
match self.store(self.deref(addr)) { let b =
Addr::Usize(b) => { match addr {
let iter = self.gather_attr_vars_created_since(b); Addr::Usize(b) => {
Some(b)
let var_list_addr = Addr::HeapCell(self.heap.to_list(iter));
let list_addr = self[temp_v!(2)];
self.unify(var_list_addr, list_addr);
}
Addr::Con(h) if self.heap.integer_at(h) => {
if let HeapCellValue::Integer(n) = self.heap.clone(h) {
if let Some(b) = n.to_usize() {
let iter = self.gather_attr_vars_created_since(b);
let var_list_addr = Addr::HeapCell(self.heap.to_list(iter));
let list_addr = self[temp_v!(2)];
self.unify(var_list_addr, list_addr);
} else {
self.fail = true;
}
} else {
unreachable!()
} }
} _ => {
_ => { match Number::try_from((addr, &self.heap)) {
self.fail = true; Ok(Number::Integer(n)) => {
} n.to_usize()
}
Ok(Number::Fixnum(n)) => {
usize::try_from(n).ok()
}
_ => {
self.fail = true;
return Ok(());
}
}
}
};
if let Some(b) = b {
let iter = self.gather_attr_vars_created_since(b);
let var_list_addr = Addr::HeapCell(self.heap.to_list(iter));
let list_addr = self[temp_v!(2)];
self.unify(var_list_addr, list_addr);
} }
} }
&SystemClauseType::GetContinuationChunk => { &SystemClauseType::GetContinuationChunk => {
@@ -2327,51 +2358,58 @@ impl MachineState {
CWILCallPolicy::new_in_place(call_policy); CWILCallPolicy::new_in_place(call_policy);
} }
match (a1, a2) { let n =
(Addr::Usize(bp), Addr::Con(h)) match Number::try_from((a2, &self.heap)) {
| (Addr::CutPoint(bp), Addr::Con(h)) Ok(Number::Integer(n)) => {
if self.heap.integer_at(h) => { Integer::from(&*n.clone())
if let HeapCellValue::Integer(n) = self.heap.clone(h) { }
match call_policy.downcast_mut::<CWILCallPolicy>().ok() { Ok(Number::Fixnum(n)) => {
Some(call_policy) => { Integer::from(n)
let count = call_policy.add_limit(Integer::from(&*n), bp); }
let count = self.heap.to_unifiable( _ => {
HeapCellValue::Integer(Rc::new(count.clone())) let stub = MachineError::functor_stub(
); clause_name!("call_with_inference_limit"),
3,
);
let a3 = self[temp_v!(3)]; let type_error = self.error_form(
MachineError::type_error(
self.heap.h(),
ValidType::Integer,
a2,
),
stub,
);
self.unify(a3, count); self.throw_exception(type_error);
} return Ok(());
None => { }
panic!( };
"install_inference_counter: should have installed \\
CWILCallPolicy." match a1 {
) Addr::Usize(bp) | Addr::CutPoint(bp) => {
} match call_policy.downcast_mut::<CWILCallPolicy>().ok() {
} Some(call_policy) => {
} else { let count = call_policy.add_limit(n, bp).clone();
unreachable!() let count = self.heap.to_unifiable(
HeapCellValue::Integer(Rc::new(count))
);
let a3 = self[temp_v!(3)];
self.unify(a3, count);
}
None => {
panic!(
"install_inference_counter: should have installed \\
CWILCallPolicy."
)
} }
} }
_ => {
let stub = MachineError::functor_stub(
clause_name!("call_with_inference_limit"),
3,
);
let type_error = self.error_form(
MachineError::type_error(
self.heap.h(),
ValidType::Integer,
a2,
),
stub,
);
self.throw_exception(type_error)
} }
}; _ => {
unreachable!();
}
}
} }
&SystemClauseType::ModuleExists => { &SystemClauseType::ModuleExists => {
let module = self.store(self.deref(self[temp_v!(1)])); let module = self.store(self.deref(self[temp_v!(1)]));
@@ -2582,9 +2620,9 @@ impl MachineState {
match a1 { match a1 {
Addr::Usize(bp) | Addr::CutPoint(bp) => { Addr::Usize(bp) | Addr::CutPoint(bp) => {
let count = call_policy.remove_limit(bp); let count = call_policy.remove_limit(bp).clone();
let count = self.heap.to_unifiable( let count = self.heap.to_unifiable(
HeapCellValue::Integer(Rc::new(count.clone())), HeapCellValue::Integer(Rc::new(count)),
); );
let a2 = self[temp_v!(2)]; let a2 = self[temp_v!(2)];
@@ -3029,29 +3067,24 @@ impl MachineState {
Addr::CharCode(c) => { Addr::CharCode(c) => {
Integer::from(c) Integer::from(c)
} }
Addr::Con(h) if self.heap.integer_at(h) => { _ => {
if let HeapCellValue::Integer(ref n) = &self.heap[h] { match Number::try_from((seed, &self.heap)) {
Integer::from(&**n) Ok(Number::Fixnum(n)) => {
} else { Integer::from(n)
unreachable!() }
} Ok(Number::Integer(n)) => {
} Integer::from(n.as_ref())
Addr::Con(h) if self.heap.rational_at(h) => { }
if let HeapCellValue::Rational(r) = &self.heap[h] { Ok(Number::Rational(n))
if r.denom() == &1 { if n.denom() == &1 => {
r.numer().clone() n.numer().clone()
} else { }
_ => {
self.fail = true; self.fail = true;
return Ok(()); return Ok(());
} }
} else {
unreachable!()
} }
} }
_ => {
self.fail = true;
return Ok(());
}
}; };
let mut rand = RANDOM_STATE.borrow_mut(); let mut rand = RANDOM_STATE.borrow_mut();
@@ -3195,43 +3228,33 @@ impl MachineState {
} }
}; };
let arity = match self.store(self.deref(arity)) { let arity = self.store(self.deref(arity));
Addr::Con(h) if self.heap.integer_at(h) => {
if let HeapCellValue::Integer(ref n) = &self.heap[h] { let arity =
n.clone() match Number::try_from((arity, &self.heap)) {
} else { Ok(Number::Fixnum(n)) => {
Integer::from(n)
}
Ok(Number::Integer(n)) => {
Integer::from(n.as_ref())
}
_ => {
unreachable!() unreachable!()
} }
} };
_ => {
unreachable!()
}
};
let first_idx = match indices let first_idx = match indices
.code_dir .code_dir
.get(&(name.clone(), arity.to_usize().unwrap())) .get(&(name.clone(), arity.to_usize().unwrap()))
{ {
Some(ref idx) => { Some(ref idx) if idx.local().is_some() => {
if let Some(idx) = idx.local() { if let Some(idx) = idx.local() {
idx idx
} else { } else {
let arity = arity.to_usize().unwrap(); unreachable!()
let stub = MachineError::functor_stub(name.clone(), arity);
let h = self.heap.h();
let err = MachineError::existence_error(
h,
ExistenceError::Procedure(name, arity),
);
let err = self.error_form(err, stub);
self.throw_exception(err);
return Ok(());
} }
} }
None => { _ => {
let arity = arity.to_usize().unwrap(); let arity = arity.to_usize().unwrap();
let stub = MachineError::functor_stub(name.clone(), arity); let stub = MachineError::functor_stub(name.clone(), arity);
let h = self.heap.h(); let h = self.heap.h();
@@ -3279,7 +3302,7 @@ impl MachineState {
let mut printer = HCPrinter::new(&self, &indices.op_dir, PrinterOutputter::new()); let mut printer = HCPrinter::new(&self, &indices.op_dir, PrinterOutputter::new());
if let &Addr::Con(h) = &ignore_ops { if let &Addr::Con(h) = &ignore_ops {
if let HeapCellValue::Atom(ref name, _) = &self.heap[h] { if let HeapCellValue::Atom(ref name, _) = &self.heap[h] {
printer.ignore_ops = name.as_str() == "true"; printer.ignore_ops = name.as_str() == "true";
} else { } else {
unreachable!() unreachable!()
@@ -3287,7 +3310,7 @@ impl MachineState {
} }
if let &Addr::Con(h) = &numbervars { if let &Addr::Con(h) = &numbervars {
if let HeapCellValue::Atom(ref name, _) = &self.heap[h] { if let HeapCellValue::Atom(ref name, _) = &self.heap[h] {
printer.numbervars = name.as_str() == "true"; printer.numbervars = name.as_str() == "true";
} else { } else {
unreachable!() unreachable!()
@@ -3295,23 +3318,32 @@ impl MachineState {
} }
if let &Addr::Con(h) = &quoted { if let &Addr::Con(h) = &quoted {
if let HeapCellValue::Atom(ref name, _) = &self.heap[h] { if let HeapCellValue::Atom(ref name, _) = &self.heap[h] {
printer.quoted = name.as_str() == "true"; printer.quoted = name.as_str() == "true";
} else { } else {
unreachable!() unreachable!()
} }
} }
if let &Addr::Con(h) = &max_depth { match Number::try_from((max_depth, &self.heap)) {
if let HeapCellValue::Integer(ref n) = &self.heap[h] { Ok(Number::Fixnum(n)) => {
if let Ok(n) = usize::try_from(n) {
printer.max_depth = n;
} else {
self.fail = true;
return Ok(());
}
}
Ok(Number::Integer(n)) => {
if let Some(n) = n.to_usize() { if let Some(n) = n.to_usize() {
printer.max_depth = n; printer.max_depth = n;
} else { } else {
self.fail = true; self.fail = true;
return Ok(()); return Ok(());
} }
} else { }
unreachable!() _ => {
unreachable!();
} }
} }

View File

@@ -362,7 +362,7 @@ impl MachineState {
wam.code_repo.cached_query = code; wam.code_repo.cached_query = code;
self.cp = LocalCodePtr::TopLevel(0, 0); self.cp = LocalCodePtr::TopLevel(0, 0);
self.at_end_of_expansion = false; self.at_end_of_expansion = false;
self.flags.double_quotes = DoubleQuotes::Chars; self.flags.double_quotes = DoubleQuotes::Chars;

View File

@@ -13,6 +13,7 @@ use indexmap::{IndexMap, IndexSet};
use std::borrow::BorrowMut; use std::borrow::BorrowMut;
use std::cell::Cell; use std::cell::Cell;
use std::collections::VecDeque; use std::collections::VecDeque;
use std::convert::TryFrom;
use std::mem; use std::mem;
use std::ops::DerefMut; use std::ops::DerefMut;
use std::rc::Rc; use std::rc::Rc;
@@ -211,8 +212,8 @@ fn setup_op_decl(
}; };
let prec = match *terms.pop().unwrap() { let prec = match *terms.pop().unwrap() {
Term::Constant(_, Constant::Integer(bi)) => match bi.to_usize() { Term::Constant(_, Constant::Fixnum(bi)) => match usize::try_from(bi) {
Some(n) if n <= 1200 => n, Ok(n) if n <= 1200 => n,
_ => return Err(ParserError::InconsistentEntry), _ => return Err(ParserError::InconsistentEntry),
}, },
_ => return Err(ParserError::InconsistentEntry), _ => return Err(ParserError::InconsistentEntry),
@@ -232,8 +233,13 @@ fn setup_predicate_indicator(term: &mut Term) -> Result<PredicateKey, ParserErro
let arity = arity let arity = arity
.to_constant() .to_constant()
.and_then(|c| c.to_integer()) .and_then(|c| {
.and_then(|n| n.to_usize()) match c {
Constant::Integer(n) => n.to_usize(),
Constant::Fixnum(n) => usize::try_from(n).ok(),
_ => None
}
})
.ok_or(ParserError::InvalidModuleExport)?; .ok_or(ParserError::InvalidModuleExport)?;
let name = name let name = name
@@ -246,7 +252,7 @@ fn setup_predicate_indicator(term: &mut Term) -> Result<PredicateKey, ParserErro
} else { } else {
Ok((name, arity + 2)) Ok((name, arity + 2))
} }
} }
_ => Err(ParserError::InvalidModuleExport), _ => Err(ParserError::InvalidModuleExport),
} }
} }
@@ -344,7 +350,7 @@ fn setup_use_module_decl(mut terms: Vec<Box<Term>>) -> Result<ModuleSource, Pars
fn setup_double_quotes(mut terms: Vec<Box<Term>>) -> Result<DoubleQuotes, ParserError> { fn setup_double_quotes(mut terms: Vec<Box<Term>>) -> Result<DoubleQuotes, ParserError> {
let dbl_quotes = *terms.pop().unwrap(); let dbl_quotes = *terms.pop().unwrap();
match terms[0].as_ref() { match terms[0].as_ref() {
Term::Constant(_, Constant::Atom(ref name, _)) Term::Constant(_, Constant::Atom(ref name, _))
if name.as_str() == "double_quotes" => { if name.as_str() == "double_quotes" => {
@@ -629,26 +635,26 @@ fn setup_declaration<'a, 'b, 'c>(
match term { match term {
Term::Clause(_, name, mut terms, _) => Term::Clause(_, name, mut terms, _) =>
match (name.as_str(), terms.len()) { match (name.as_str(), terms.len()) {
("dynamic", 1) => { ("dynamic", 1) => {
let (name, arity) = setup_predicate_indicator(&mut *terms.pop().unwrap())?; let (name, arity) = setup_predicate_indicator(&mut *terms.pop().unwrap())?;
Ok(Declaration::Dynamic(name, arity)) Ok(Declaration::Dynamic(name, arity))
} }
("initialization", 1) => { ("initialization", 1) => {
let mut rel_worker = RelationWorker::new(flags, line_num, col_num); let mut rel_worker = RelationWorker::new(flags, line_num, col_num);
let query_terms = rel_worker.setup_query(indices, terms, false)?; let query_terms = rel_worker.setup_query(indices, terms, false)?;
let queue = rel_worker.parse_queue(indices)?; let queue = rel_worker.parse_queue(indices)?;
Ok(Declaration::ModuleInitialization(query_terms, queue)) Ok(Declaration::ModuleInitialization(query_terms, queue))
} }
("module", 2) => ("module", 2) =>
Ok(Declaration::Module(setup_module_decl(terms, indices.atom_tbl())?)), Ok(Declaration::Module(setup_module_decl(terms, indices.atom_tbl())?)),
("op", 3) => ("op", 3) =>
Ok(Declaration::Op(setup_op_decl(terms, indices.atom_tbl())?)), Ok(Declaration::Op(setup_op_decl(terms, indices.atom_tbl())?)),
("non_counted_backtracking", 1) => { ("non_counted_backtracking", 1) => {
let (name, arity) = setup_predicate_indicator(&mut *terms.pop().unwrap())?; let (name, arity) = setup_predicate_indicator(&mut *terms.pop().unwrap())?;
Ok(Declaration::NonCountedBacktracking(name, arity)) Ok(Declaration::NonCountedBacktracking(name, arity))
} }
("set_prolog_flag", 2) => { ("set_prolog_flag", 2) => {
Ok(Declaration::SetPrologFlag(setup_double_quotes(terms)?)) Ok(Declaration::SetPrologFlag(setup_double_quotes(terms)?))
} }
@@ -656,27 +662,31 @@ fn setup_declaration<'a, 'b, 'c>(
let mut term = *terms.pop().unwrap(); let mut term = *terms.pop().unwrap();
match setup_predicate_indicator(&mut term) { match setup_predicate_indicator(&mut term) {
Ok((name, arity)) => Ok((name, arity)) => {
Ok(Declaration::MultiFile(MultiFileIndicator::LocalScoped(name, arity))), Ok(Declaration::MultiFile(MultiFileIndicator::LocalScoped(name, arity)))
_ => }
_ => {
setup_scoped_predicate_indicator(&mut term) setup_scoped_predicate_indicator(&mut term)
.map(|key| { .map(|key| {
Declaration::MultiFile(MultiFileIndicator::ModuleScoped(key)) Declaration::MultiFile(MultiFileIndicator::ModuleScoped(key))
}) })
}
} }
} }
("use_module", 1) => { ("use_module", 1) => {
Ok(Declaration::UseModule(setup_use_module_decl(terms)?)) Ok(Declaration::UseModule(setup_use_module_decl(terms)?))
} }
("use_module", 2) => { ("use_module", 2) => {
let (name, exports) = setup_qualified_import(terms, indices.atom_tbl())?; let (name, exports) = setup_qualified_import(terms, indices.atom_tbl())?;
Ok(Declaration::UseQualifiedModule(name, exports)) Ok(Declaration::UseQualifiedModule(name, exports))
} }
_ => { _ => {
Err(ParserError::InconsistentEntry) Err(ParserError::InconsistentEntry)
} }
}, },
_ => Err(ParserError::InconsistentEntry), _ => {
Err(ParserError::InconsistentEntry)
}
} }
} }
@@ -1249,7 +1259,7 @@ impl<'a> TopLevelBatchWorker<'a> {
while !self.term_stream.eof()? { while !self.term_stream.eof()? {
let term = self.term_stream.read_term(&indices.op_dir)?; let term = self.term_stream.read_term(&indices.op_dir)?;
// if is_consistent is false, preds is non-empty. // if is_consistent is false, preds is non-empty.
let term = if !term.is_consistent(&preds) { let term = if !term.is_consistent(&preds) {
self.process_result(indices, &mut preds)?; self.process_result(indices, &mut preds)?;

View File

@@ -105,7 +105,7 @@ macro_rules! functor_term {
); );
(constant($h:expr, $e:expr), $arity:expr, $aux_lens:expr, $addendum:ident) => ( (constant($h:expr, $e:expr), $arity:expr, $aux_lens:expr, $addendum:ident) => (
from_constant!($e, $h, $arity, $aux_lens, $addendum) from_constant!($e, $h, $arity, $aux_lens, $addendum)
); );
(constant($e:expr), $arity:expr, $aux_lens:expr, $addendum:ident) => ( (constant($e:expr), $arity:expr, $aux_lens:expr, $addendum:ident) => (
from_constant!($e, 0, $arity, $aux_lens, $addendum) from_constant!($e, 0, $arity, $aux_lens, $addendum)
); );
@@ -138,6 +138,9 @@ macro_rules! from_constant {
&Constant::CharCode(c) => { &Constant::CharCode(c) => {
HeapCellValue::Addr(Addr::CharCode(c)) HeapCellValue::Addr(Addr::CharCode(c))
} }
&Constant::Fixnum(n) => {
HeapCellValue::Addr(Addr::Fixnum(n))
}
&Constant::Integer(ref n) => { &Constant::Integer(ref n) => {
HeapCellValue::Integer(n.clone()) HeapCellValue::Integer(n.clone())
} }
@@ -152,7 +155,7 @@ macro_rules! from_constant {
let h = len + $arity + 1 + $addendum.h() + $over_h; let h = len + $arity + 1 + $addendum.h() + $over_h;
$addendum.put_constant(Constant::String(s.clone())); $addendum.put_constant(Constant::String(s.clone()));
HeapCellValue::Addr(Addr::PStrLocation(h, 0)) HeapCellValue::Addr(Addr::PStrLocation(h, 0))
} }
&Constant::Usize(u) => { &Constant::Usize(u) => {

View File

@@ -30,16 +30,17 @@
; ;
Term = [Item] -> !, Term = [Item] -> !,
( atom(Item) -> ( atom(Item) ->
( Item == user -> ( Item == user ->
catch('$$compile_batch', E, '$print_exception_with_check'(E)) catch('$$compile_batch', E, '$print_exception_with_check'(E))
; consult(Item) ; consult(Item)
) )
; ;
catch(throw(error(type_error(atom, Item), repl/0)), catch(throw(error(type_error(atom, Item), repl/0)),
E, E,
'$print_exception_with_check'(E)) '$print_exception_with_check'(E))
) )
; '$submit_query_and_print_results'(Term, VarList) ;
'$submit_query_and_print_results'(Term, VarList)
). ).
'$submit_query_and_print_results'(Term0, VarList) :- '$submit_query_and_print_results'(Term0, VarList) :-
@@ -55,10 +56,10 @@
'$needs_bracketing'(Value, Op) :- '$needs_bracketing'(Value, Op) :-
catch((functor(Value, F, _), catch((functor(Value, F, _),
current_op(EqPrec, EqSpec, Op), current_op(EqPrec, EqSpec, Op),
current_op(FPrec, _, F)), current_op(FPrec, _, F)),
_, _,
false), false),
( EqPrec < FPrec -> true ( EqPrec < FPrec -> true
; '$quoted_token'(F) -> true ; '$quoted_token'(F) -> true
; EqPrec == FPrec, ; EqPrec == FPrec,
@@ -225,10 +226,8 @@
). ).
'$gather_goals'([], VarList, Goals) :- '$gather_goals'([], VarList, Goals) :-
'$get_attr_var_queue_beyond'(0, AttrVars),
'$gather_query_vars'(VarList, QueryVars), '$gather_query_vars'(VarList, QueryVars),
'$call_attribute_goals'(QueryVars, AttrVars), copy_term(QueryVars, QueryVars, Goals).
'$fetch_attribute_goals'(Goals).
'$gather_goals'([Var = Value | Pairs], VarList, Goals) :- '$gather_goals'([Var = Value | Pairs], VarList, Goals) :-
( ( nonvar(Value) ( ( nonvar(Value)
; '$is_a_different_variable'(Pairs, Value) ; '$is_a_different_variable'(Pairs, Value)
@@ -253,27 +252,27 @@
'$module_export'(Source, PI) :- '$module_export'(Source, PI) :-
( nonvar(PI) -> ( nonvar(PI) ->
( PI = Name / Arity -> ( PI = Name / Arity ->
( var(Name) -> throw(error(instantiation_error, Source)) ( var(Name) -> throw(error(instantiation_error, Source))
; integer(Arity) -> ; integer(Arity) ->
( \+ atom(Name) -> throw(error(type_error(atom, Name), Source)) ( \+ atom(Name) -> throw(error(type_error(atom, Name), Source))
; Arity < 0 -> throw(error(domain_error(not_less_than_zero, Arity), Source)) ; Arity < 0 -> throw(error(domain_error(not_less_than_zero, Arity), Source))
; true ; true
) )
; throw(error(type_error(integer, Arity), Source)) ; throw(error(type_error(integer, Arity), Source))
) )
; PI = op(Prec, Spec, Name) -> ; PI = op(Prec, Spec, Name) ->
( integer(Prec) -> ( integer(Prec) ->
( \+ atom(Name) -> ( \+ atom(Name) ->
throw(error(type_error(atom, Name), Source)) throw(error(type_error(atom, Name), Source))
; Prec < 0 -> ; Prec < 0 ->
throw(error(domain_error(not_less_than_zero, Prec), Source)) throw(error(domain_error(not_less_than_zero, Prec), Source))
; Prec > 1200 -> ; Prec > 1200 ->
throw(error(domain_error(operator_precision, Prec), Source)) throw(error(domain_error(operator_precision, Prec), Source))
; memberchk(Spec, [xfy, yfx, xfx, fx, fy, yf, xf]) ; memberchk(Spec, [xfy, yfx, xfx, fx, fy, yf, xf])
; throw(error(domain_error(operator_specification, Spec), Source)) ; throw(error(domain_error(operator_specification, Spec), Source))
) )
; throw(error(type_error(integer, Prec), Source)) ; throw(error(type_error(integer, Prec), Source))
) )
; throw(error(type_error(module_export, PI), Source)) ; throw(error(type_error(module_export, PI), Source))
) )
; throw(error(instantiation_error, Source)) ; throw(error(instantiation_error, Source))
@@ -334,10 +333,10 @@ expand_goals(UnexpandedGoals, ExpandedGoals) :-
), ),
( Goals = (Goal0, Goals0) -> ( Goals = (Goal0, Goals0) ->
( expand_goals(Goal0, Goal1) -> ( expand_goals(Goal0, Goal1) ->
expand_goals(Goals0, Goals1), expand_goals(Goals0, Goals1),
thread_goals(Goal1, ExpandedGoals, Goals1, (',')) thread_goals(Goal1, ExpandedGoals, Goals1, (','))
; expand_goals(Goals0, Goals1), ; expand_goals(Goals0, Goals1),
ExpandedGoals = (Goal0, Goals1) ExpandedGoals = (Goal0, Goals1)
) )
; Goals = (Goals0 -> Goals1) -> ; Goals = (Goals0 -> Goals1) ->
expand_goals(Goals0, ExpandedGoals0), expand_goals(Goals0, ExpandedGoals0),
@@ -358,9 +357,9 @@ thread_goals(Goals0, Goals1, Hole, Functor) :-
nonvar(Goals0), nonvar(Goals0),
( Goals0 = [G | Gs] -> ( Goals0 = [G | Gs] ->
( Gs == [] -> ( Gs == [] ->
Goals1 =.. [Functor, G, Hole] Goals1 =.. [Functor, G, Hole]
; Goals1 =.. [Functor, G, Goals2], ; Goals1 =.. [Functor, G, Goals2],
thread_goals(Gs, Goals2, Hole, Functor) thread_goals(Gs, Goals2, Hole, Functor)
) )
; Goals1 =.. [Functor, Goals0, Hole] ; Goals1 =.. [Functor, Goals0, Hole]
). ).
@@ -369,9 +368,9 @@ thread_goals(Goals0, Goals1, Functor) :-
nonvar(Goals0), nonvar(Goals0),
( Goals0 = [G | Gs] -> ( Goals0 = [G | Gs] ->
( Gs = [] -> ( Gs = [] ->
Goals1 = G Goals1 = G
; Goals1 =.. [Functor, G, Goals2], ; Goals1 =.. [Functor, G, Goals2],
thread_goals(Gs, Goals2, Functor) thread_goals(Gs, Goals2, Functor)
) )
; Goals1 = Goals0 ; Goals1 = Goals0
). ).

View File

@@ -187,6 +187,7 @@ impl fmt::Display for Addr {
&Addr::Char(c) => write!(f, "Addr::Char({})", c), &Addr::Char(c) => write!(f, "Addr::Char({})", c),
&Addr::CharCode(c) => write!(f, "Addr::CharCode({})", c), &Addr::CharCode(c) => write!(f, "Addr::CharCode({})", c),
&Addr::EmptyList => write!(f, "Addr::EmptyList"), &Addr::EmptyList => write!(f, "Addr::EmptyList"),
&Addr::Fixnum(n) => write!(f, "Addr::Fixnum({})", n),
&Addr::Float(fl) => write!(f, "Addr::Float({})", fl), &Addr::Float(fl) => write!(f, "Addr::Float({})", fl),
&Addr::CutPoint(cp) => write!(f, "Addr::CutPoint({})", cp), &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),
@@ -305,13 +306,13 @@ impl fmt::Display for Line {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self { match self {
&Line::Arithmetic(ref arith_instr) => write!(f, "{}", arith_instr), &Line::Arithmetic(ref arith_instr) => write!(f, "{}", arith_instr),
&Line::Choice(ref choice_instr) => write!(f, "{}", choice_instr), &Line::Choice(ref choice_instr) => write!(f, "{}", choice_instr),
&Line::Control(ref control_instr) => write!(f, "{}", control_instr), &Line::Control(ref control_instr) => write!(f, "{}", control_instr),
&Line::Cut(ref cut_instr) => write!(f, "{}", cut_instr), &Line::Cut(ref cut_instr) => write!(f, "{}", cut_instr),
&Line::Fact(ref fact_instr) => write!(f, "{}", fact_instr), &Line::Fact(ref fact_instr) => write!(f, "{}", fact_instr),
&Line::Indexing(ref indexing_instr) => write!(f, "{}", indexing_instr), &Line::Indexing(ref indexing_instr) => write!(f, "{}", indexing_instr),
&Line::IndexedChoice(ref indexed_choice_instr) => write!(f, "{}", indexed_choice_instr), &Line::IndexedChoice(ref indexed_choice_instr) => write!(f, "{}", indexed_choice_instr),
&Line::Query(ref query_instr) => write!(f, "{}", query_instr), &Line::Query(ref query_instr) => write!(f, "{}", query_instr),
} }
} }
} }
@@ -319,6 +320,7 @@ impl fmt::Display for Line {
impl fmt::Display for Number { impl fmt::Display for Number {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self { match self {
&Number::Fixnum(n) => write!(f, "{}", n),
&Number::Float(fl) => write!(f, "{}", fl), &Number::Float(fl) => write!(f, "{}", fl),
&Number::Integer(ref bi) => write!(f, "{}", bi), &Number::Integer(ref bi) => write!(f, "{}", bi),
&Number::Rational(ref r) => write!(f, "{}", r), &Number::Rational(ref r) => write!(f, "{}", r),

View File

@@ -35,7 +35,7 @@ test_queries_on_call_with_inference_limit :-
[true, 2], [true, 2],
[inference_limit_exceeded, _]]), [inference_limit_exceeded, _]]),
findall([X,R1,R2], findall([X,R1,R2],
(call_with_inference_limit(g(X), 4, R1), (call_with_inference_limit(g(X), 4, R1),
call_with_inference_limit(g(X), 5, R2)), call_with_inference_limit(g(X), 5, R2)),
[[1,true,!], [[1,true,!],
[2,true,!], [2,true,!],

View File

@@ -23,6 +23,6 @@ test_queries_on_facts :-
retract(p(_,_,_)), retract(p(_,_,_)),
assertz(p(Z, h(Z, W), f(W))), assertz(p(Z, h(Z, W), f(W))),
p(f(f(a)), h(f(f(a)), f(a)), f(f(a))), p(f(f(a)), h(f(f(a)), f(a)), f(f(a))),
retract(p(Z, h(Z, W), f(W))).[ retract(p(Z, h(Z, W), f(W))).
:- initialization(test_queries_on_facts). :- initialization(test_queries_on_facts).

View File

@@ -62,4 +62,3 @@ cleanup :- abolish(p/3),
abolish(h/1). abolish(h/1).
:- initialization(test_queries_on_rules). :- initialization(test_queries_on_rules).