]> Repositorios git - scryer-prolog.git/commitdiff
use fixnums in place of bignums where possible
authorMark Thom <[email protected]>
Mon, 6 Apr 2020 02:32:16 +0000 (20:32 -0600)
committerMark Thom <[email protected]>
Mon, 6 Apr 2020 02:32:16 +0000 (20:32 -0600)
26 files changed:
Cargo.lock
Cargo.toml
src/prolog/arithmetic.rs
src/prolog/clause_types.rs
src/prolog/codegen.rs
src/prolog/forms.rs
src/prolog/heap_print.rs
src/prolog/indexing.rs
src/prolog/lib/assoc.pl
src/prolog/lib/builtins.pl
src/prolog/machine/arithmetic_ops.rs
src/prolog/machine/dynamic_database.rs
src/prolog/machine/heap.rs
src/prolog/machine/machine_indices.rs
src/prolog/machine/machine_state.rs
src/prolog/machine/machine_state_impl.rs
src/prolog/machine/mod.rs
src/prolog/machine/system_calls.rs
src/prolog/machine/term_expansion.rs
src/prolog/machine/toplevel.rs
src/prolog/macros.rs
src/prolog/toplevel.pl
src/prolog/write.rs
src/tests/call_with_inference_limit.pl
src/tests/facts.pl
src/tests/rules.pl

index ea022e957687c708d786a0efb3a70669c32c3b01..526c4fc7a46908815bfe7327255f924d1d3618b7 100644 (file)
@@ -444,7 +444,7 @@ dependencies = [
 
 [[package]]
 name = "prolog_parser"
-version = "0.8.48"
+version = "0.8.49"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "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)",
  "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)",
- "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)",
  "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)",
@@ -791,7 +791,7 @@ dependencies = [
 "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 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 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"
index b8a576235f2bf0e820e5ad346b2495273c7f3b9e..76c6c6e24155ceca4c177878eaf86ebc223b8d90 100644 (file)
@@ -25,7 +25,7 @@ libc = "0.2.62"
 nix = "0.15.0"
 num-rug-adapter = { optional = true, version = "0.1.1" }
 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"
 rug = { version = "1.4.0", optional = true }
 rustyline = "6.0.0"
\ No newline at end of file
index 3520cb1baa0e153043340a0585632f0dd088d0c7..3b84bf3031f8cade8f2d209ce42fda694da430a8 100644 (file)
@@ -6,6 +6,7 @@ use crate::prolog::forms::*;
 use crate::prolog::instructions::*;
 use crate::prolog::iterators::*;
 
+use crate::prolog::machine::heap::*;
 use crate::prolog::machine::machine_errors::*;
 use crate::prolog::machine::machine_indices::*;
 
@@ -15,6 +16,7 @@ use crate::prolog::rug::{Assign, Integer, Rational};
 
 use std::cell::Cell;
 use std::cmp::{max, min, Ordering};
+use std::convert::TryFrom;
 use std::f64;
 use std::num::FpCategory;
 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> {
         match c {
+            &Constant::Fixnum(n) => self
+                .interm
+                .push(ArithmeticTerm::Number(Number::Fixnum(n))),
             &Constant::Integer(ref n) => self
                 .interm
                 .push(ArithmeticTerm::Number(Number::Integer(n.clone()))),
@@ -316,18 +321,25 @@ impl<'a> ArithmeticEvaluator<'a> {
 }
 
 // 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 {
-        &Number::Integer(ref n) => RefOrOwned::Borrowed(n),
+        &Number::Integer(_) => {
+            RefOrOwned::Borrowed(n)
+        }
         &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) => {
             let r_ref = r.fract_floor_ref();
             let (mut fract, mut floor) = (Rational::new(), Integer::new());
-
             (&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.
 pub fn rnd_f(n: &Number) -> f64 {
     match n {
+        &Number::Fixnum(n) => n as f64,
         &Number::Integer(ref n) => n.to_f64(),
         &Number::Float(OrderedFloat(f)) => f,
         &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> {
     classify_float(n.to_f64(), rnd_f)
 }
 
+#[inline]
 fn float_r_to_f(r: &Rational) -> Result<f64, EvalError> {
     classify_float(r.to_f64(), rnd_f)
 }
 
+#[inline]
 fn add_f(f1: f64, f2: f64) -> Result<OrderedFloat<f64>, EvalError> {
     Ok(OrderedFloat(classify_float(f1 + f2, rnd_f)?))
 }
 
+#[inline]
 fn mul_f(f1: f64, f2: f64) -> Result<OrderedFloat<f64>, EvalError> {
     Ok(OrderedFloat(classify_float(f1 * f2, rnd_f)?))
 }
 
+#[inline]
 fn div_f(f1: f64, f2: f64) -> Result<OrderedFloat<f64>, EvalError> {
     if FpCategory::Zero == f2.classify() {
         Err(EvalError::ZeroDivisor)
@@ -399,8 +422,27 @@ impl Add<Number> for Number {
 
     fn add(self, rhs: Number) -> Self::Output {
         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)) => {
-                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::Float(OrderedFloat(n2)), Number::Integer(n1)) => {
@@ -408,7 +450,7 @@ impl Add<Number> for Number {
             }
             (Number::Integer(n1), Number::Rational(n2))
           | (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::Float(OrderedFloat(n2)), Number::Rational(n1)) => {
@@ -418,7 +460,7 @@ impl Add<Number> for Number {
                 Ok(Number::Float(add_f(f1, f2)?))
             }
             (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 {
         match self {
+            Number::Fixnum(n) => Number::Fixnum(-n),
             Number::Integer(n) => Number::Integer(Rc::new(-Integer::from(&*n))),
             Number::Float(OrderedFloat(f)) => Number::Float(OrderedFloat(-f)),
             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 {
         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)) => {
                 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 {
         match (self, rhs) {
-            (Number::Integer(n1), Number::Integer(n2)) => Ok(Number::Float(div_f(
-                float_i_to_f(&n1)?,
-                float_i_to_f(&n2)?,
-            )?)),
+            (Number::Fixnum(n1), Number::Fixnum(n2)) => {
+                Ok(Number::Float(div_f(
+                    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))) => {
                 Ok(Number::Float(div_f(float_i_to_f(&n1)?, n2)?))
             }
             (Number::Float(OrderedFloat(n2)), Number::Integer(n1)) => {
                 Ok(Number::Float(div_f(n2, float_i_to_f(&n1)?)?))
             }
-            (Number::Integer(n1), Number::Rational(n2)) => Ok(Number::Float(div_f(
-                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::Integer(n1), Number::Rational(n2)) => {
+                Ok(Number::Float(div_f(
+                    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(n1), Number::Float(OrderedFloat(n2))) => {
                 Ok(Number::Float(div_f(float_r_to_f(&n1)?, n2)?))
             }
@@ -514,25 +624,47 @@ impl Div<Number> for Number {
     }
 }
 
-impl PartialOrd for Number {
-    fn partial_cmp(&self, rhs: &Number) -> Option<Ordering> {
+impl PartialEq for Number {
+    fn eq(&self, rhs: &Self) -> bool {
         match (self, 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)),
+            (&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 {
+    fn partial_cmp(&self, rhs: &Number) -> Option<Ordering> {
+        Some(self.cmp(rhs))
+    }
+}
+
 impl Ord for Number {
     fn cmp(&self, rhs: &Number) -> Ordering {
         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(_), Number::Float(_)) => Ordering::Greater,
             (&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.
 pub fn binary_pow(mut n: Integer, power: &Integer) -> Integer {
     let mut power = Integer::from(power.abs_ref());
index 5068ffc26d769dc442069947685a6de1e1b03522..4abdd8fd5e6ac5dd5ce3fbec6d469bbabfbf015c 100644 (file)
@@ -159,7 +159,6 @@ pub enum SystemClauseType {
     AtomCodes,
     AtomLength,
     BindFromRegister,
-    CallAttributeGoals,
     CallContinuation,
     CharCode,
     CharsToNumber,
@@ -179,7 +178,6 @@ pub enum SystemClauseType {
     EnqueueAttributedVar,
     ExpandGoal,
     ExpandTerm,
-    FetchAttributeGoals,
     FetchGlobalVar,
     FetchGlobalVarWithOffset,
     GetChar,
@@ -277,7 +275,6 @@ impl SystemClauseType {
             &SystemClauseType::AtomCodes => clause_name!("$atom_codes"),
             &SystemClauseType::AtomLength => clause_name!("$atom_length"),
             &SystemClauseType::BindFromRegister => clause_name!("$bind_from_register"),
-            &SystemClauseType::CallAttributeGoals => clause_name!("$call_attribute_goals"),
             &SystemClauseType::CallContinuation => clause_name!("$call_continuation"),
             &SystemClauseType::CharCode => clause_name!("$char_code"),
             &SystemClauseType::CharsToNumber => clause_name!("$chars_to_number"),
@@ -308,7 +305,6 @@ impl SystemClauseType {
             &SystemClauseType::EnqueueAttributedVar => clause_name!("$enqueue_attr_var"),
             &SystemClauseType::ExpandTerm => clause_name!("$expand_term"),
             &SystemClauseType::ExpandGoal => clause_name!("$expand_goal"),
-            &SystemClauseType::FetchAttributeGoals => clause_name!("$fetch_attribute_goals"),
             &SystemClauseType::FetchGlobalVar => clause_name!("$fetch_global_var"),
             &SystemClauseType::FetchGlobalVarWithOffset => {
                 clause_name!("$fetch_global_var_with_offset")
@@ -429,7 +425,6 @@ impl SystemClauseType {
             ("$module_assertz", 5) => Some(SystemClauseType::ModuleAssertDynamicPredicateToBack),
             ("$asserta", 4) => Some(SystemClauseType::AssertDynamicPredicateToFront),
             ("$assertz", 4) => Some(SystemClauseType::AssertDynamicPredicateToBack),
-            ("$call_attribute_goals", 2) => Some(SystemClauseType::CallAttributeGoals),
             ("$call_continuation", 1) => Some(SystemClauseType::CallContinuation),
             ("$char_code", 2) => Some(SystemClauseType::CharCode),
             ("$chars_to_number", 2) => Some(SystemClauseType::CharsToNumber),
@@ -456,7 +451,6 @@ impl SystemClauseType {
             ("$is_partial_string", 1) => Some(SystemClauseType::IsPartialString),
             ("$expand_term", 2) => Some(SystemClauseType::ExpandTerm),
             ("$expand_goal", 2) => Some(SystemClauseType::ExpandGoal),
-            ("$fetch_attribute_goals", 1) => Some(SystemClauseType::FetchAttributeGoals),
             ("$fetch_global_var", 2) => Some(SystemClauseType::FetchGlobalVar),
             ("$fetch_global_var_with_offset", 3) => Some(SystemClauseType::FetchGlobalVarWithOffset),
             ("$get_char", 1) => Some(SystemClauseType::GetChar),
index 13cb33f8590d144879461747b31e636e04ab28d2..944e1c9ed1378c95d6d6dc12a6c3e6576ee02396 100644 (file)
@@ -446,7 +446,8 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<TermMarker> {
                 }
             },
             &InlinedClauseType::IsInteger(..) => match terms[0].as_ref() {
-                &Term::Constant(_, Constant::Integer(_)) => {
+                &Term::Constant(_, Constant::Integer(_)) |
+                &Term::Constant(_, Constant::Fixnum(_)) => {
                     code.push(succeed!());
                 }
                 &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))))
                 }
             }
-            &Term::Constant(_, ref c @ Constant::Integer(_)) => {
+            &Term::Constant(_, ref c @ Constant::Integer(_)) |
+            &Term::Constant(_, ref c @ Constant::Fixnum(_)) => {
                 code.push(Line::Query(put_constant!(
                     Level::Shallow,
                     c.clone(),
@@ -708,7 +710,7 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<TermMarker> {
             match fact_instr {
                 &mut FactInstruction::UnifyValue(r) => {
                     if !safe_vars.contains(&r) {
-                        *fact_instr = FactInstruction::UnifyLocalValue(r);                        
+                        *fact_instr = FactInstruction::UnifyLocalValue(r);
                         safe_vars.insert(r);
                     }
                 }
index f26361deda2e57e29d08d88f8d463c58fe884fcf..ece57a04a401789a4b71ded339cbc6c8c653a720 100644 (file)
@@ -12,6 +12,7 @@ use indexmap::IndexMap;
 
 use std::cell::Cell;
 use std::collections::VecDeque;
+use std::convert::TryFrom;
 use std::path::PathBuf;
 use std::rc::Rc;
 
@@ -573,11 +574,33 @@ pub struct Module {
     pub listing_src: ListingSource,
  }
 
-#[derive(Clone, PartialEq, Eq)]
+#[derive(Clone)]
 pub enum Number {
     Float(OrderedFloat<f64>),
     Integer(Rc<Integer>),
     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 {
@@ -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 {
     #[inline]
     fn into(self) -> HeapCellValue {
         match self {
+            Number::Fixnum(n) => HeapCellValue::Addr(Addr::Fixnum(n)),
             Number::Integer(n) => HeapCellValue::Integer(n),
             Number::Float(f) => HeapCellValue::Addr(Addr::Float(f)),
             Number::Rational(r) => HeapCellValue::Rational(r),
@@ -597,10 +633,27 @@ impl Into<HeapCellValue> for 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]
     pub fn is_positive(&self) -> bool {
         match self {
+            &Number::Fixnum(n) => n > 0,
             &Number::Integer(ref n) => &**n > &0,
             &Number::Float(OrderedFloat(f)) => f.is_sign_positive(),
             &Number::Rational(ref r) => &**r > &0,
@@ -610,6 +663,7 @@ impl Number {
     #[inline]
     pub fn is_negative(&self) -> bool {
         match self {
+            &Number::Fixnum(n) => n < 0,
             &Number::Integer(ref n) => &**n < &0,
             &Number::Float(OrderedFloat(f)) => f.is_sign_negative(),
             &Number::Rational(ref r) => &**r < &0,
@@ -619,6 +673,7 @@ impl Number {
     #[inline]
     pub fn is_zero(&self) -> bool {
         match self {
+            &Number::Fixnum(n) => n == 0,
             &Number::Integer(ref n) => &**n == &0,
             &Number::Float(f) => f == OrderedFloat(0f64),
             &Number::Rational(ref r) => &**r == &0,
@@ -628,9 +683,15 @@ impl Number {
     #[inline]
     pub fn abs(self) -> 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::Rational(r) => Number::Rational(Rc::new(Rational::from(r.abs_ref()))),
+            Number::Rational(r) => Number::from(Rational::from(r.abs_ref())),
         }
     }
 }
index 036597522c0c68aaf4f32b5913b0e5252c0a9ff5..6d252695562021c35859984231f51c5eb6f78c2a 100644 (file)
@@ -12,6 +12,7 @@ use crate::prolog::rug::Integer;
 use indexmap::{IndexMap, IndexSet};
 
 use std::cell::Cell;
+use std::convert::TryFrom;
 use std::iter::{FromIterator, once};
 use std::ops::{Range, RangeFrom};
 use std::rc::Rc;
@@ -263,30 +264,27 @@ fn is_numbered_var(ct: &ClauseType, arity: usize) -> bool {
 
 #[inline]
 fn negated_op_needs_bracketing(iter: &HCPreOrderIterator, op: &Option<DirectedOp>) -> bool {
-    if let &Some(ref op) = op {
-        op.is_negative_sign() && iter.leftmost_leaf_has_property(|addr, heap| {
-            match addr {
-                Addr::Con(h) => {
-                    match &heap[h] {
-                        HeapCellValue::Integer(ref n) => {
-                            &**n > &0
-                        }
-                        &HeapCellValue::Rational(ref r) => {
-                            &**r > &0
-                        }
-                        _ => {
-                            false
-                        }
+    if let Some(ref op) = op {
+        op.is_negative_sign() &&
+            iter.leftmost_leaf_has_property(|addr, heap| {
+                match Number::try_from((addr, heap)) {
+                    Ok(Number::Fixnum(n)) => {
+                        n > 0
+                    }
+                    Ok(Number::Float(f)) => {
+                        f > OrderedFloat(0f64)
+                    }
+                    Ok(Number::Integer(n)) => {
+                        &*n > &0
+                    }
+                    Ok(Number::Rational(n)) => {
+                        &*n > &0
+                    }
+                    _ => {
+                        false
                     }
                 }
-                Addr::Float(f) => {
-                    f > OrderedFloat(0f64)
-                }
-                _ => {
-                    false
-                }
-            }
-        })
+            })
     } else {
         false
     }
@@ -311,14 +309,19 @@ fn numbervar(n: Integer) -> Var {
 
 impl MachineState {
     pub fn numbervar(&self, offset: &Integer, addr: Addr) -> Option<Var> {
-        match self.store(self.deref(addr)) {
-            Addr::Con(h) => {
-                if let &HeapCellValue::Integer(ref n) = &self.heap[h] {
-                    if &**n >= &0 {
-                        Some(numbervar(Integer::from(offset + &**n)))
-                    } else {
-                        None
-                    }
+        let addr = self.store(self.deref(addr));
+
+        match Number::try_from((addr, &self.heap)) {
+            Ok(Number::Fixnum(n)) => {
+                if n >= 0 {
+                    Some(numbervar(Integer::from(offset + Integer::from(n))))
+                } else {
+                    None
+                }
+            }
+            Ok(Number::Integer(n)) => {
+                if &*n >= &0 {
+                    Some(numbervar(Integer::from(offset + &*n)))
                 } else {
                     None
                 }
@@ -1336,6 +1339,9 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
             &HeapCellValue::Addr(Addr::Float(n)) => {
                 self.print_number(Number::Float(n), &op);
             }
+            &HeapCellValue::Addr(Addr::Fixnum(n)) => {
+                self.print_number(Number::Fixnum(n), &op);
+            }
             &HeapCellValue::Addr(Addr::Usize(u)) => {
                 self.append_str(&format!("{}", u));
             }
index 2bcfc6c3de0963dede20caedeec72ae9e76f073c..59e83a78c04981b240e6b23a1295e88590a922e4 100644 (file)
@@ -1,11 +1,13 @@
 use prolog_parser::ast::*;
 
 use crate::prolog::instructions::*;
+use crate::prolog::rug::Integer;
 
 use indexmap::IndexMap;
 
 use std::collections::VecDeque;
 use std::hash::Hash;
+use std::rc::Rc;
 
 #[derive(Clone, Copy)]
 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) {
         match first_arg {
             &Term::Clause(_, ref name, ref terms, _) => {
@@ -63,29 +100,12 @@ impl CodeOffsets {
                 let is_initial_index = self.lists.is_empty();
                 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) => {
-                if let Constant::Atom(ref name, _) = constant {
-                    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));
-                    }
-                }
-                
-                let code = self.constants.entry(constant.clone()).or_insert(Vec::new());
+                self.intercept_constant(constant, index);
+
+                let code = self.constants
+                    .entry(constant.clone())
+                    .or_insert(vec![]);
 
                 let is_initial_index = code.is_empty();
                 code.push(Self::add_index(is_initial_index, index));
index b99b1c4b0ec0e69aa39fd777f6cbd8d57a54e106..2ebf1a8e0bf7b0c48e57e8eb05f708e7c735d4d5 100644 (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
 */
 
-/*                                       
+/*
 :- meta_predicate
     map_assoc(1, ?),
     map_assoc(2, ?, ?).
 */
-                                         
+
 %!  empty_assoc(?Assoc) is semidet.
 %
 %   Is true if Assoc is the empty association list.
index cff33c7773778f0ed1775177c4477333876de4bc..61efae1ca6982df39392bb6c7ea3dde6289c8de3 100644 (file)
@@ -1024,7 +1024,7 @@ subsumes_term(General, Specific) :-
 
 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).
 
index cf2a3b9187d18629ce172f9282faf35ae44b7cc7..29137604bdbc97b5f0da795fc0dcf99a5c4de127 100644 (file)
@@ -10,6 +10,7 @@ use crate::prolog::ordered_float::*;
 use crate::prolog::rug::{Integer, Rational};
 
 use std::cmp;
+use std::convert::TryFrom;
 use std::f64;
 use std::mem;
 use std::rc::Rc;
@@ -24,13 +25,61 @@ macro_rules! try_numeric_result {
             Err(e) => {
                 let caller_copy =
                     $caller.iter().map(|v| v.context_free_clone()).collect();
-                
+
                 Err($s.error_form(MachineError::evaluation_error(e), caller_copy))
             }
         }
     );
 }
 
+fn isize_gcd(n1: isize, n2: isize) -> Option<isize> {
+    if n1 == 0 {
+        return n2.checked_abs().map(|n| n as isize);
+    }
+
+    if n2 == 0 {
+        return n1.checked_abs().map(|n| n as isize);
+    }
+
+    let n1 = n1.checked_abs();
+    let n2 = n2.checked_abs();
+
+    let mut n1 = if let Some(n1) = n1 { n1 } else { return None };
+    let mut n2 = if let Some(n2) = n2 { n2 } else { return None };
+
+    let mut shift = 0;
+
+    while ((n1 | n2) & 1) == 0 {
+        shift += 1;
+        n1 >>= 1;
+        n2 >>= 1;
+    }
+
+    while (n1 & 1) == 0 {
+        n1 >>= 1;
+    }
+
+    loop {
+        while (n2 & 1) == 0 {
+            n2 >>= 1;
+        }
+
+        if n1 > n2 {
+            let t = n2;
+            n2 = n1;
+            n1 = t;
+        }
+
+        n2 -= n1;
+
+        if n2 == 0 {
+            break;
+        }
+    }
+
+    Some(n1 << shift as isize)
+}
+
 impl MachineState {
     pub(crate)
     fn get_number(&mut self, at: &ArithmeticTerm) -> Result<Number, MachineStub> {
@@ -40,7 +89,7 @@ impl MachineState {
             }
             &ArithmeticTerm::Interm(i) => Ok(mem::replace(
                 &mut self.interms[i - 1],
-                Number::Integer(Rc::new(Integer::from(0))),
+                Number::Fixnum(0),
             )),
             &ArithmeticTerm::Number(ref n) => {
                 Ok(n.clone())
@@ -54,6 +103,9 @@ impl MachineState {
         n: Number,
     ) -> Result<Rc<Rational>, MachineError> {
         match n {
+            Number::Fixnum(n) => {
+                Ok(Rc::new(Rational::from(n)))
+            }
             Number::Rational(r) => {
                 Ok(r)
             }
@@ -80,7 +132,7 @@ impl MachineState {
         caller: MachineStub,
     ) -> Result<(Rc<Rational>, MachineStub), MachineStub> {
         let n = self.get_number(at)?;
-        
+
         match self.rational_from_number(n) {
             Ok(r) => Ok((r, caller)),
             Err(e) => Err(self.error_form(e, caller))
@@ -114,7 +166,7 @@ impl MachineState {
                             let r2 = r1.and_then(|r1| {
                                 self.rational_from_number(a2).map(|r2| (r1, r2))
                             });
-                                                 
+
                             match r2 {
                                 Ok((r1, r2)) => {
                                     let result = Number::Rational(Rc::new(self.rdiv(r1, r2)?));
@@ -123,19 +175,19 @@ impl MachineState {
                                 Err(e) => {
                                     return Err(self.error_form(e, caller));
                                 }
-                            }                            
+                            }
                         }
-                        "//" => interms.push(Number::Integer(Rc::new(self.idiv(a1, a2)?))),
-                        "div" => interms.push(Number::Integer(Rc::new(self.int_floor_div(a1, a2)?))),
-                        ">>" => interms.push(Number::Integer(Rc::new(self.shr(a1, a2)?))),
-                        "<<" => interms.push(Number::Integer(Rc::new(self.shl(a1, a2)?))),
-                        "/\\" => interms.push(Number::Integer(Rc::new(self.and(a1, a2)?))),
-                        "\\/" => interms.push(Number::Integer(Rc::new(self.or(a1, a2)?))),
-                        "xor" => interms.push(Number::Integer(Rc::new(self.xor(a1, a2)?))),
-                        "mod" => interms.push(Number::Integer(Rc::new(self.modulus(a1, a2)?))),
-                        "rem" => interms.push(Number::Integer(Rc::new(self.remainder(a1, a2)?))),
+                        "//" => interms.push(self.idiv(a1, a2)?),
+                        "div" => interms.push(self.int_floor_div(a1, a2)?),
+                        ">>" => interms.push(self.shr(a1, a2)?),
+                        "<<" => interms.push(self.shl(a1, a2)?),
+                        "/\\" => interms.push(self.and(a1, a2)?),
+                        "\\/" => interms.push(self.or(a1, a2)?),
+                        "xor" => interms.push(self.xor(a1, a2)?),
+                        "mod" => interms.push(self.modulus(a1, a2)?),
+                        "rem" => interms.push(self.remainder(a1, a2)?),
                         "atan2" => interms.push(Number::Float(OrderedFloat(self.atan2(a1, a2)?))),
-                        "gcd" => interms.push(Number::Integer(Rc::new(self.gcd(a1, a2)?))),
+                        "gcd" => interms.push(self.gcd(a1, a2)?),
                         _ => {
                             return Err(self.error_form(MachineError::instantiation_error(), caller))
                         }
@@ -158,27 +210,30 @@ impl MachineState {
                         "atan" => interms.push(Number::Float(OrderedFloat(self.atan(a1)?))),
                         "abs" => interms.push(a1.abs()),
                         "float" => interms.push(Number::Float(OrderedFloat(self.float(a1)?))),
-                        "truncate" => interms.push(Number::Integer(Rc::new(self.truncate(a1)))),
-                        "round" => interms.push(Number::Integer(Rc::new(self.round(a1)?))),
-                        "ceiling" => interms.push(Number::Integer(Rc::new(self.ceiling(a1)))),
-                        "floor" => interms.push(Number::Integer(Rc::new(self.floor(a1)))),
-                        "\\" => interms.push(Number::Integer(Rc::new(self.bitwise_complement(a1)?))),
-                        "sign" => interms.push(Number::Integer(Rc::new(self.sign(a1)))),
+                        "truncate" => interms.push(self.truncate(a1)),
+                        "round" => interms.push(self.round(a1)?),
+                        "ceiling" => interms.push(self.ceiling(a1)),
+                        "floor" => interms.push(self.floor(a1)),
+                        "\\" => interms.push(self.bitwise_complement(a1)?),
+                        "sign" => interms.push(self.sign(a1)),
                         _ => {
                             return Err(self.error_form(MachineError::instantiation_error(), caller));
                         }
                     }
                 }
-                &HeapCellValue::Integer(ref n) => {
-                    interms.push(Number::Integer(n.clone()))
+                &HeapCellValue::Addr(Addr::CharCode(n)) => {
+                    interms.push(Number::Integer(Rc::new(Integer::from(n))));
+                }
+                &HeapCellValue::Addr(Addr::Fixnum(n)) => {
+                    interms.push(Number::Fixnum(n));
                 }
                 &HeapCellValue::Addr(Addr::Float(n)) => {
                     interms.push(Number::Float(n))
                 }
-                &HeapCellValue::Addr(Addr::Usize(n)) => {
-                    interms.push(Number::Integer(Rc::new(Integer::from(n))));
+                &HeapCellValue::Integer(ref n) => {
+                    interms.push(Number::Integer(n.clone()))
                 }
-                &HeapCellValue::Addr(Addr::CharCode(n)) => {
+                &HeapCellValue::Addr(Addr::Usize(n)) => {
                     interms.push(Number::Integer(Rc::new(Integer::from(n))));
                 }
                 &HeapCellValue::Rational(ref n) => {
@@ -210,9 +265,11 @@ impl MachineState {
     }
 
     pub(crate)
-    fn int_floor_div(&self, n1: Number, n2: Number) -> Result<Integer, MachineStub> {
+    fn int_floor_div(&self, n1: Number, n2: Number) -> Result<Number, MachineStub> {
         match n1 / n2 {
-            Ok(result) => Ok(rnd_i(&result).to_owned()),
+            Ok(result) => {
+                Ok(rnd_i(&result).to_owned())
+            }
             Err(e) => {
                 let stub = MachineError::functor_stub(clause_name!("(div)"), 2);
                 Err(self.error_form(
@@ -226,8 +283,57 @@ impl MachineState {
     }
 
     pub(crate)
-    fn idiv(&self, n1: Number, n2: Number) -> Result<Integer, MachineStub> {
+    fn idiv(&self, n1: Number, n2: Number) -> Result<Number, MachineStub> {
         match (n1, n2) {
+            (Number::Fixnum(n1), Number::Fixnum(n2)) => {
+                if n2 == 0 {
+                    let stub = MachineError::functor_stub(clause_name!("(//)"), 2);
+
+                    Err(self.error_form(
+                        MachineError::evaluation_error(
+                            EvalError::ZeroDivisor
+                        ),
+                        stub,
+                    ))
+                } else {
+                    if let Some(result) = n1.checked_div(n2) {
+                        Ok(Number::from(result))
+                    } else {
+                        let n1 = Integer::from(n1);
+                        let n2 = Integer::from(n2);
+
+                        Ok(Number::from(n1 / n2))
+                    }
+                }
+            }
+            (Number::Fixnum(n1), Number::Integer(n2)) => {
+                if &*n2 == &0 {
+                    let stub = MachineError::functor_stub(clause_name!("(//)"), 2);
+
+                    Err(self.error_form(
+                        MachineError::evaluation_error(
+                            EvalError::ZeroDivisor
+                        ),
+                        stub,
+                    ))
+                } else {
+                    Ok(Number::from(Integer::from(n1) / &*n2))
+                }
+            }
+            (Number::Integer(n2), Number::Fixnum(n1)) => {
+                if n1 == 0 {
+                    let stub = MachineError::functor_stub(clause_name!("(//)"), 2);
+
+                    Err(self.error_form(
+                        MachineError::evaluation_error(
+                            EvalError::ZeroDivisor
+                        ),
+                        stub,
+                    ))
+                } else {
+                    Ok(Number::from(&*n2 / Integer::from(n1)))
+                }
+            }
             (Number::Integer(n1), Number::Integer(n2)) => {
                 if &*n2 == &0 {
                     let stub = MachineError::functor_stub(clause_name!("(//)"), 2);
@@ -239,10 +345,10 @@ impl MachineState {
                         stub,
                     ))
                 } else {
-                    Ok(<(Integer, Integer)>::from(n1.div_rem_ref(&*n2)).0)
+                    Ok(Number::from(<(Integer, Integer)>::from(n1.div_rem_ref(&*n2)).0))
                 }
             }
-            (Number::Integer(_), n2) => {
+            (Number::Fixnum(_), n2) | (Number::Integer(_), n2) => {
                 let stub = MachineError::functor_stub(clause_name!("(//)"), 2);
 
                 Err(self.error_form(
@@ -302,6 +408,68 @@ impl MachineState {
         }
 
         match (n1, n2) {
+            (Number::Fixnum(n1), Number::Fixnum(n2)) => {
+                if n1 != 1 && n2 < 0 {
+                    let n = Number::from(n1);
+                    let stub = MachineError::functor_stub(clause_name!("^"), 2);
+
+                    Err(self.error_form(
+                        MachineError::type_error(
+                            self.heap.h(),
+                            ValidType::Float,
+                            n
+                        ),
+                        stub,
+                    ))
+                } else {
+                    if let Ok(n2) = u32::try_from(n2) {
+                        if let Some(result) = n1.checked_pow(n2) {
+                            return Ok(Number::from(result));
+                        }
+                    }
+
+                    let n1 = Integer::from(n1);
+                    let n2 = Integer::from(n2);
+
+                    Ok(Number::from(binary_pow(n1, &n2)))
+                }
+            }
+            (Number::Fixnum(n1), Number::Integer(n2)) => {
+                if n1 != 1 && &*n2 < &0 {
+                    let n = Number::from(n1);
+                    let stub = MachineError::functor_stub(clause_name!("^"), 2);
+
+                    Err(self.error_form(
+                        MachineError::type_error(
+                            self.heap.h(),
+                            ValidType::Float,
+                            n
+                        ),
+                        stub,
+                    ))
+                } else {
+                    let n1 = Integer::from(n1);
+                    Ok(Number::from(binary_pow(n1, n2.as_ref())))
+                }
+            }
+            (Number::Integer(n1), Number::Fixnum(n2)) => {
+                if &*n1 != &1 && n2 < 0 {
+                    let n = Number::Integer(n1);
+                    let stub = MachineError::functor_stub(clause_name!("^"), 2);
+
+                    Err(self.error_form(
+                        MachineError::type_error(
+                            self.heap.h(),
+                            ValidType::Float,
+                            n
+                        ),
+                        stub,
+                    ))
+                } else {
+                    let n2 = Integer::from(n2);
+                    Ok(Number::from(binary_pow(n1.as_ref().clone(), &n2)))
+                }
+            }
             (Number::Integer(n1), Number::Integer(n2)) => {
                 if &*n1 != &1 && &*n2 < &0 {
                     let n = Number::Integer(n1);
@@ -316,7 +484,7 @@ impl MachineState {
                         stub,
                     ))
                 } else {
-                    Ok(Number::Integer(Rc::new(binary_pow(n1.as_ref().clone(), n2.as_ref()))))
+                    Ok(Number::from(binary_pow(n1.as_ref().clone(), n2.as_ref())))
                 }
             }
             (n1, Number::Integer(n2)) => {
@@ -344,10 +512,22 @@ impl MachineState {
     }
 
     pub(crate)
-    fn gcd(&self, n1: Number, n2: Number) -> Result<Integer, MachineStub> {
+    fn gcd(&self, n1: Number, n2: Number) -> Result<Number, MachineStub> {
         match (n1, n2) {
+            (Number::Fixnum(n1), Number::Fixnum(n2)) => {
+                if let Some(result) = isize_gcd(n1, n2) {
+                    Ok(Number::Fixnum(result))
+                } else {
+                    Ok(Number::from(Integer::from(n1).gcd(&Integer::from(n2))))
+                }
+            }
+            (Number::Fixnum(n1), Number::Integer(n2)) |
+            (Number::Integer(n2), Number::Fixnum(n1)) => {
+                let n1 = Integer::from(n1);
+                Ok(Number::from(Integer::from(n2.gcd_ref(&n1))))
+            }
             (Number::Integer(n1), Number::Integer(n2)) => {
-                Ok(Integer::from(n1.gcd_ref(&n2)))
+                Ok(Number::from(Integer::from(n1.gcd_ref(&n2))))
             }
             (Number::Float(f), _) | (_, Number::Float(f)) => {
                 let n = Number::Float(f);
@@ -403,8 +583,28 @@ impl MachineState {
         }
 
         match (n1, n2) {
+            (Number::Fixnum(n1), Number::Fixnum(n2)) => {
+                if let Ok(n2) = u32::try_from(n2) {
+                    if let Some(result) = n1.checked_pow(n2) {
+                        return Ok(Number::from(result));
+                    }
+                }
+
+                let n1 = Integer::from(n1);
+                let n2 = Integer::from(n2);
+
+                Ok(Number::from(binary_pow(n1, &n2)))
+            }
+            (Number::Fixnum(n1), Number::Integer(n2)) => {
+                let n1 = Integer::from(n1);
+                Ok(Number::from(binary_pow(n1, n2.as_ref())))
+            }
+            (Number::Integer(n1), Number::Fixnum(n2)) => {
+                let n2 = Integer::from(n2);
+                Ok(Number::from(binary_pow(n1.as_ref().clone(), &n2)))
+            }
             (Number::Integer(n1), Number::Integer(n2)) => {
-                Ok(Number::Integer(Rc::new(binary_pow(n1.as_ref().clone(), &*n2))))
+                Ok(Number::from(binary_pow(n1.as_ref().clone(), &*n2)))
             }
             (n1, n2) => {
                 self.float_pow(n1, n2)
@@ -412,6 +612,7 @@ impl MachineState {
         }
     }
 
+    #[inline]
     pub(crate)
     fn unary_float_fn_template<FloatFn>(&self, n1: Number, f: FloatFn) -> Result<f64, MachineStub>
     where
@@ -425,46 +626,55 @@ impl MachineState {
         try_numeric_result!(self, f1, stub)
     }
 
+    #[inline]
     pub(crate)
     fn sin(&self, n1: Number) -> Result<f64, MachineStub> {
         self.unary_float_fn_template(n1, |f| f.sin())
     }
 
+    #[inline]
     pub(crate)
     fn cos(&self, n1: Number) -> Result<f64, MachineStub> {
         self.unary_float_fn_template(n1, |f| f.cos())
     }
 
+    #[inline]
     pub(crate)
     fn tan(&self, n1: Number) -> Result<f64, MachineStub> {
         self.unary_float_fn_template(n1, |f| f.tan())
     }
 
+    #[inline]
     pub(crate)
     fn log(&self, n1: Number) -> Result<f64, MachineStub> {
         self.unary_float_fn_template(n1, |f| f.log(f64::consts::E))
     }
 
+    #[inline]
     pub(crate)
     fn exp(&self, n1: Number) -> Result<f64, MachineStub> {
         self.unary_float_fn_template(n1, |f| f.exp())
     }
 
+    #[inline]
     pub(crate)
     fn asin(&self, n1: Number) -> Result<f64, MachineStub> {
         self.unary_float_fn_template(n1, |f| f.asin())
     }
 
+    #[inline]
     pub(crate)
     fn acos(&self, n1: Number) -> Result<f64, MachineStub> {
         self.unary_float_fn_template(n1, |f| f.acos())
     }
 
+    #[inline]
     pub(crate)
     fn atan(&self, n1: Number) -> Result<f64, MachineStub> {
         self.unary_float_fn_template(n1, |f| f.atan())
     }
 
+    #[inline]
     pub(crate)
     fn sqrt(&self, n1: Number) -> Result<f64, MachineStub> {
         if n1.is_negative() {
@@ -475,24 +685,28 @@ impl MachineState {
         self.unary_float_fn_template(n1, |f| f.sqrt())
     }
 
+    #[inline]
     pub(crate)
     fn float(&self, n: Number) -> Result<f64, MachineStub> {
         let stub = MachineError::functor_stub(clause_name!("(is)"), 2);
         try_numeric_result!(self, result_f(&n, rnd_f), stub)
     }
 
+    #[inline]
     pub(crate)
-    fn floor(&self, n1: Number) -> Integer {
+    fn floor(&self, n1: Number) -> Number {
         rnd_i(&n1).to_owned()
     }
 
+    #[inline]
     pub(crate)
-    fn ceiling(&self, n1: Number) -> Integer {
+    fn ceiling(&self, n1: Number) -> Number {
         -self.floor(-n1)
     }
 
+    #[inline]
     pub(crate)
-    fn truncate(&self, n: Number) -> Integer {
+    fn truncate(&self, n: Number) -> Number {
         if n.is_negative() {
             -self.floor(n.abs())
         } else {
@@ -501,7 +715,7 @@ impl MachineState {
     }
 
     pub(crate)
-    fn round(&self, n: Number) -> Result<Integer, MachineStub> {
+    fn round(&self, n: Number) -> Result<Number, MachineStub> {
         let stub = MachineError::functor_stub(clause_name!("(is)"), 2);
 
         let result = n + Number::Float(OrderedFloat(0.5f64));
@@ -511,14 +725,43 @@ impl MachineState {
     }
 
     pub(crate)
-    fn shr(&self, n1: Number, n2: Number) -> Result<Integer, MachineStub> {
+    fn shr(&self, n1: Number, n2: Number) -> Result<Number, MachineStub> {
         let stub = MachineError::functor_stub(clause_name!("(>>)"), 2);
 
         match (n1, n2) {
+            (Number::Fixnum(n1), Number::Fixnum(n2)) => {
+                if let Ok(n2) = u32::try_from(n2) {
+                    if let Some(result) = n1.checked_shr(n2) {
+                        return Ok(Number::from(result));
+                    }
+                }
+
+                let n1 = Integer::from(n1);
+                let n2 = Integer::from(n2);
+
+                match n2.to_u32() {
+                    Some(n2) => Ok(Number::from(n1 >> n2)),
+                    _ => Ok(Number::from(n1 >> u32::max_value())),
+                }
+            }
+            (Number::Fixnum(n1), Number::Integer(n2)) => {
+                let n1 = Integer::from(n1);
+
+                match n2.to_u32() {
+                    Some(n2) => Ok(Number::from(n1 >> n2)),
+                    _ => Ok(Number::from(n1 >> u32::max_value())),
+                }
+            }
+            (Number::Integer(n1), Number::Fixnum(n2)) => {
+                match u32::try_from(n2) {
+                    Ok(n2) => Ok(Number::from(Integer::from(&*n1 >> n2))),
+                    _ => Ok(Number::from(Integer::from(&*n1 >> u32::max_value()))),
+                }
+            }
             (Number::Integer(n1), Number::Integer(n2)) =>
                 match n2.to_u32() {
-                    Some(n2) => Ok(Integer::from(&*n1 >> n2)),
-                    _ => Ok(Integer::from(&*n1 >> u32::max_value())),
+                    Some(n2) => Ok(Number::from(Integer::from(&*n1 >> n2))),
+                    _ => Ok(Number::from(Integer::from(&*n1 >> u32::max_value()))),
                 },
             (Number::Integer(_), n2) => Err(self.error_form(
                 MachineError::type_error(
@@ -540,13 +783,42 @@ impl MachineState {
     }
 
     pub(crate)
-    fn shl(&self, n1: Number, n2: Number) -> Result<Integer, MachineStub> {
+    fn shl(&self, n1: Number, n2: Number) -> Result<Number, MachineStub> {
         let stub = MachineError::functor_stub(clause_name!("(<<)"), 2);
 
         match (n1, n2) {
+            (Number::Fixnum(n1), Number::Fixnum(n2)) => {
+                if let Ok(n2) = u32::try_from(n2) {
+                    if let Some(result) = n1.checked_shl(n2) {
+                        return Ok(Number::from(result));
+                    }
+                }
+
+                let n1 = Integer::from(n1);
+                let n2 = Integer::from(n2);
+
+                match n2.to_u32() {
+                    Some(n2) => Ok(Number::from(n1 << n2)),
+                    _ => Ok(Number::from(n1 << u32::max_value())),
+                }
+            }
+            (Number::Fixnum(n1), Number::Integer(n2)) => {
+                let n1 = Integer::from(n1);
+
+                match n2.to_u32() {
+                    Some(n2) => Ok(Number::from(n1 << n2)),
+                    _ => Ok(Number::from(n1 << u32::max_value())),
+                }
+            }
+            (Number::Integer(n1), Number::Fixnum(n2)) => {
+                match u32::try_from(n2) {
+                    Ok(n2) => Ok(Number::from(Integer::from(&*n1 << n2))),
+                    _ => Ok(Number::from(Integer::from(&*n1 << u32::max_value()))),
+                }
+            }
             (Number::Integer(n1), Number::Integer(n2)) => match n2.to_u32() {
-                Some(n2) => Ok(Integer::from(&*n1 << n2)),
-                _ => Ok(Integer::from(&*n1 << u32::max_value())),
+                Some(n2) => Ok(Number::from(Integer::from(&*n1 << n2))),
+                _ => Ok(Number::from(Integer::from(&*n1 << u32::max_value()))),
             },
             (Number::Integer(_), n2) => Err(self.error_form(
                 MachineError::type_error(
@@ -568,11 +840,12 @@ impl MachineState {
     }
 
     pub(crate)
-    fn bitwise_complement(&self, n1: Number) -> Result<Integer, MachineStub> {
+    fn bitwise_complement(&self, n1: Number) -> Result<Number, MachineStub> {
         let stub = MachineError::functor_stub(clause_name!("(\\)"), 2);
 
         match n1 {
-            Number::Integer(n1) => Ok(Integer::from(!&*n1)),
+            Number::Fixnum(n) => Ok(Number::Fixnum(!n)),
+            Number::Integer(n1) => Ok(Number::from(Integer::from(!&*n1))),
             _ => Err(self.error_form(
                 MachineError::type_error(
                     self.heap.h(),
@@ -585,14 +858,24 @@ impl MachineState {
     }
 
     pub(crate)
-    fn xor(&self, n1: Number, n2: Number) -> Result<Integer, MachineStub> {
+    fn xor(&self, n1: Number, n2: Number) -> Result<Number, MachineStub> {
         let stub = MachineError::functor_stub(clause_name!("(xor)"), 2);
 
         match (n1, n2) {
+            (Number::Fixnum(n1), Number::Fixnum(n2)) => {
+                Ok(Number::from(n1 ^ n2))
+            }
+            (Number::Fixnum(n1), Number::Integer(n2)) => {
+                let n1 = Integer::from(n1);
+                Ok(Number::from(n1 ^ &*n2))
+            }
+            (Number::Integer(n1), Number::Fixnum(n2)) => {
+                Ok(Number::from(&*n1 ^ Integer::from(n2)))
+            }
             (Number::Integer(n1), Number::Integer(n2)) => {
-                Ok(Integer::from(&*n1 ^ &*n2))
+                Ok(Number::from(Integer::from(&*n1 ^ &*n2)))
             }
-            (Number::Integer(_), n2) => {
+            (Number::Integer(_), n2) | (Number::Fixnum(_), n2) => {
                 Err(self.error_form(
                     MachineError::type_error(
                         self.heap.h(),
@@ -616,19 +899,33 @@ impl MachineState {
     }
 
     pub(crate)
-    fn and(&self, n1: Number, n2: Number) -> Result<Integer, MachineStub> {
+    fn and(&self, n1: Number, n2: Number) -> Result<Number, MachineStub> {
         let stub = MachineError::functor_stub(clause_name!("(/\\)"), 2);
 
         match (n1, n2) {
-            (Number::Integer(n1), Number::Integer(n2)) => Ok(Integer::from(&*n1 & &*n2)),
-            (Number::Integer(_), n2) => Err(self.error_form(
-                MachineError::type_error(
-                    self.heap.h(),
-                    ValidType::Integer,
-                    n2,
-                ),
-                stub,
-            )),
+            (Number::Fixnum(n1), Number::Fixnum(n2)) => {
+                Ok(Number::from(n1 & n2))
+            }
+            (Number::Fixnum(n1), Number::Integer(n2)) => {
+                let n1 = Integer::from(n1);
+                Ok(Number::from(n1 & &*n2))
+            }
+            (Number::Integer(n1), Number::Fixnum(n2)) => {
+                Ok(Number::from(&*n1 & Integer::from(n2)))
+            }
+            (Number::Integer(n1), Number::Integer(n2)) => {
+                Ok(Number::from(Integer::from(&*n1 & &*n2)))
+            }
+            (Number::Integer(_), n2) | (Number::Fixnum(_), n2) => {
+                Err(self.error_form(
+                    MachineError::type_error(
+                        self.heap.h(),
+                        ValidType::Integer,
+                        n2,
+                    ),
+                    stub,
+                ))
+            }
             (n1, _) => Err(self.error_form(
                 MachineError::type_error(
                     self.heap.h(),
@@ -641,10 +938,83 @@ impl MachineState {
     }
 
     pub(crate)
-    fn modulus(&self, x: Number, y: Number) -> Result<Integer, MachineStub> {
+    fn or(&self, n1: Number, n2: Number) -> Result<Number, MachineStub> {
+        let stub = MachineError::functor_stub(clause_name!("(\\/)"), 2);
+
+        match (n1, n2) {
+            (Number::Fixnum(n1), Number::Fixnum(n2)) => {
+                Ok(Number::from(n1 | n2))
+            }
+            (Number::Fixnum(n1), Number::Integer(n2)) => {
+                let n1 = Integer::from(n1);
+                Ok(Number::from(n1 | &*n2))
+            }
+            (Number::Integer(n1), Number::Fixnum(n2)) => {
+                Ok(Number::from(&*n1 | Integer::from(n2)))
+            }
+            (Number::Integer(n1), Number::Integer(n2)) => {
+                Ok(Number::from(Integer::from(&*n1 | &*n2)))
+            }
+            (Number::Integer(_), n2) | (Number::Fixnum(_), n2) => {
+                Err(self.error_form(
+                    MachineError::type_error(
+                        self.heap.h(),
+                        ValidType::Integer,
+                        n2,
+                    ),
+                    stub,
+                ))
+            }
+            (n1, _) => {
+                Err(self.error_form(
+                    MachineError::type_error(
+                        self.heap.h(),
+                        ValidType::Integer,
+                        n1
+                    ),
+                    stub,
+                ))
+            }
+        }
+    }
+
+    pub(crate)
+    fn modulus(&self, x: Number, y: Number) -> Result<Number, MachineStub> {
         let stub = MachineError::functor_stub(clause_name!("(mod)"), 2);
 
         match (x, y) {
+            (Number::Fixnum(n1), Number::Fixnum(n2)) => {
+                if n2 == 0 {
+                    Err(self.error_form(
+                        MachineError::evaluation_error(EvalError::ZeroDivisor),
+                        stub,
+                    ))
+                } else {
+                    Ok(Number::from(n1 % n2))
+                }
+            }
+            (Number::Fixnum(n1), Number::Integer(n2)) => {
+                if &*n2 == &0 {
+                    Err(self.error_form(
+                        MachineError::evaluation_error(EvalError::ZeroDivisor),
+                        stub,
+                    ))
+                } else {
+                    let n1 = Integer::from(n1);
+                    Ok(Number::from(<(Integer, Integer)>::from(n1.div_rem_floor_ref(&*n2)).1))
+                }
+            }
+            (Number::Integer(n1), Number::Fixnum(n2)) => {
+                if n2 == 0 {
+                    Err(self.error_form(
+                        MachineError::evaluation_error(EvalError::ZeroDivisor),
+                        stub,
+                    ))
+                } else {
+                    let n2 = Integer::from(n2);
+                    Ok(Number::from(<(Integer, Integer)>::from(n1.div_rem_floor_ref(&n2)).1))
+                }
+            }
             (Number::Integer(x), Number::Integer(y)) => {
                 if &*y == &0 {
                     Err(self.error_form(
@@ -652,17 +1022,87 @@ impl MachineState {
                         stub,
                     ))
                 } else {
-                    Ok(<(Integer, Integer)>::from(x.div_rem_floor_ref(&*y)).1)
+                    Ok(Number::from(<(Integer, Integer)>::from(x.div_rem_floor_ref(&*y)).1))
                 }
             }
-            (Number::Integer(_), n2) => Err(self.error_form(
+            (Number::Integer(_), n2) | (Number::Fixnum(_), n2) => {
+                Err(self.error_form(
+                    MachineError::type_error(
+                        self.heap.h(),
+                        ValidType::Integer,
+                        n2,
+                    ),
+                    stub,
+                ))
+            }
+            (n1, _) => Err(self.error_form(
                 MachineError::type_error(
                     self.heap.h(),
                     ValidType::Integer,
-                    n2,
+                    n1,
                 ),
                 stub,
             )),
+        }
+    }
+
+    pub(crate)
+    fn remainder(&self, n1: Number, n2: Number) -> Result<Number, MachineStub> {
+        let stub = MachineError::functor_stub(clause_name!("(rem)"), 2);
+
+        match (n1, n2) {
+            (Number::Fixnum(n1), Number::Fixnum(n2)) => {
+                if n2 == 0 {
+                    Err(self.error_form(
+                        MachineError::evaluation_error(EvalError::ZeroDivisor),
+                        stub,
+                    ))
+                } else {
+                    Ok(Number::from(n1 % n2))
+                }
+            }
+            (Number::Fixnum(n1), Number::Integer(n2)) => {
+                if &*n2 == &0 {
+                    Err(self.error_form(
+                        MachineError::evaluation_error(EvalError::ZeroDivisor),
+                        stub,
+                    ))
+                } else {
+                    let n1 = Integer::from(n1);
+                    Ok(Number::from(n1 % &*n2))
+                }
+            }
+            (Number::Integer(n1), Number::Fixnum(n2)) => {
+                if n2 == 0 {
+                    Err(self.error_form(
+                        MachineError::evaluation_error(EvalError::ZeroDivisor),
+                        stub,
+                    ))
+                } else {
+                    let n2 = Integer::from(n2);
+                    Ok(Number::from(&*n1 % n2))
+                }
+            }
+            (Number::Integer(n1), Number::Integer(n2)) => {
+                if &*n2 == &0 {
+                    Err(self.error_form(
+                        MachineError::evaluation_error(EvalError::ZeroDivisor),
+                        stub,
+                    ))
+                } else {
+                    Ok(Number::from(Integer::from(&*n1 % &*n2)))
+                }
+            }
+            (Number::Integer(_), n2) | (Number::Fixnum(_), n2) => {
+                Err(self.error_form(
+                    MachineError::type_error(
+                        self.heap.h(),
+                        ValidType::Integer,
+                        n2,
+                    ),
+                    stub,
+                ))
+            }
             (n1, _) => Err(self.error_form(
                 MachineError::type_error(
                     self.heap.h(),
@@ -677,6 +1117,27 @@ impl MachineState {
     pub(crate)
     fn max(&self, n1: Number, n2: Number) -> Result<Number, MachineStub> {
         match (n1, n2) {
+            (Number::Fixnum(n1), Number::Fixnum(n2)) => {
+                if n1 > n2 {
+                    Ok(Number::Fixnum(n1))
+                } else {
+                    Ok(Number::Fixnum(n2))
+                }
+            }
+            (Number::Fixnum(n1), Number::Integer(n2)) => {
+                if &*n2 > &n1 {
+                    Ok(Number::Integer(n2))
+                } else {
+                    Ok(Number::Fixnum(n1))
+                }
+            }
+            (Number::Integer(n1), Number::Fixnum(n2)) => {
+                if &*n1 > &n2 {
+                    Ok(Number::Integer(n1))
+                } else {
+                    Ok(Number::Fixnum(n2))
+                }
+            }
             (Number::Integer(n1), Number::Integer(n2)) => {
                 if n1 > n2 {
                     Ok(Number::Integer(n1))
@@ -698,6 +1159,27 @@ impl MachineState {
     pub(crate)
     fn min(&self, n1: Number, n2: Number) -> Result<Number, MachineStub> {
         match (n1, n2) {
+            (Number::Fixnum(n1), Number::Fixnum(n2)) => {
+                if n1 < n2 {
+                    Ok(Number::Fixnum(n1))
+                } else {
+                    Ok(Number::Fixnum(n2))
+                }
+            }
+            (Number::Fixnum(n1), Number::Integer(n2)) => {
+                if &*n2 < &n1 {
+                    Ok(Number::Integer(n2))
+                } else {
+                    Ok(Number::Fixnum(n1))
+                }
+            }
+            (Number::Integer(n1), Number::Fixnum(n2)) => {
+                if &*n1 < &n2 {
+                    Ok(Number::Integer(n1))
+                } else {
+                    Ok(Number::Fixnum(n2))
+                }
+            }
             (Number::Integer(n1), Number::Integer(n2)) => {
                 if n1 < n2 {
                     Ok(Number::Integer(n1))
@@ -717,76 +1199,13 @@ impl MachineState {
     }
 
     pub(crate)
-    fn sign(&self, n: Number) -> Integer {
+    fn sign(&self, n: Number) -> Number {
         if n.is_positive() {
-            Integer::from(1)
+            Number::from(1)
         } else if n.is_negative() {
-            Integer::from(-1)
+            Number::from(-1)
         } else {
-            Integer::from(0)
-        }
-    }
-
-    pub(crate)
-    fn remainder(&self, n1: Number, n2: Number) -> Result<Integer, MachineStub> {
-        let stub = MachineError::functor_stub(clause_name!("(rem)"), 2);
-
-        match (n1, n2) {
-            (Number::Integer(n1), Number::Integer(n2)) => {
-                if &*n2 == &0 {
-                    Err(self
-                        .error_form(MachineError::evaluation_error(EvalError::ZeroDivisor), stub))
-                } else {
-                    Ok(Integer::from(&*n1 % &*n2))
-                }
-            }
-            (Number::Integer(_), n2) => Err(self.error_form(
-                MachineError::type_error(
-                    self.heap.h(),
-                    ValidType::Integer,
-                    n2,
-                ),
-                stub,
-            )),
-            (n1, _) => Err(self.error_form(
-                MachineError::type_error(
-                    self.heap.h(),
-                    ValidType::Integer,
-                    n1,
-                ),
-                stub,
-            )),
-        }
-    }
-
-    pub(crate)
-    fn or(&self, n1: Number, n2: Number) -> Result<Integer, MachineStub> {
-        let stub = MachineError::functor_stub(clause_name!("(\\/)"), 2);
-
-        match (n1, n2) {
-            (Number::Integer(n1), Number::Integer(n2)) => {
-                Ok(Integer::from(&*n1 | &*n2))
-            }
-            (Number::Integer(_), n2) => {
-                Err(self.error_form(
-                    MachineError::type_error(
-                        self.heap.h(),
-                        ValidType::Integer,
-                        n2,
-                    ),
-                    stub,
-                ))
-            }
-            (n1, _) => {
-                Err(self.error_form(
-                    MachineError::type_error(
-                        self.heap.h(),
-                        ValidType::Integer,
-                        n1
-                    ),
-                    stub,
-                ))
-            }
+            Number::from(0)
         }
     }
 }
index a48627719e5d0c4209bd0c7e8d6956b4dcca2528..7fd0a8c1450337adad20a63ef164354040a6b19b 100644 (file)
@@ -6,6 +6,8 @@ use crate::prolog::machine::compile::*;
 use crate::prolog::machine::machine_errors::*;
 use crate::prolog::machine::streams::*;
 
+use std::convert::TryFrom;
+
 impl Machine {
     pub(super) fn atom_tbl_of(&self, name: &ClauseName) -> TabledData<Atom> {
         match name {
@@ -52,10 +54,16 @@ impl Machine {
 
         let arity = match self.machine_st.store(self.machine_st.deref(arity)) {
             Addr::Con(h) => {
-                if let HeapCellValue::Integer(ref arity) = &self.machine_st.heap[h] {
-                    arity.to_usize().unwrap()
-                } else {
-                    unreachable!()
+                match &self.machine_st.heap[h] {
+                    HeapCellValue::Integer(ref arity) => {
+                        arity.to_usize().unwrap()
+                    }
+                    HeapCellValue::Addr(Addr::Fixnum(arity)) => {
+                        usize::try_from(*arity).unwrap()
+                    }
+                    _ => {
+                        unreachable!()
+                    }
                 }
             }
             Addr::Usize(n) => {
@@ -102,12 +110,12 @@ impl Machine {
             }
         }
     }
-    
+
     fn abolish_dynamic_clause(&mut self, name: RegType, arity: RegType) {
         let (name, arity) = self.get_predicate_key(name, arity);
 
         self.make_undefined(name.clone(), arity);
-        
+
         self.indices.remove_code_index((name.clone(), arity));
         self.indices.remove_clause_subsection(name.owning_module(), name, arity);
     }
@@ -155,7 +163,7 @@ impl Machine {
             name,
             arity,
         );
-        
+
         self.machine_st = machine_st;
 
         if let EvalSession::Error(err) = result {
@@ -239,11 +247,17 @@ impl Machine {
         let index = self.machine_st[temp_v!(3)].clone();
         let index = match self.machine_st.store(self.machine_st.deref(index)) {
             Addr::Con(h) =>
-                if let HeapCellValue::Integer(ref n) = &self.machine_st.heap[h] {
-                    n.to_usize().unwrap()
-                } else {
-                    unreachable!()
-                },
+                match &self.machine_st.heap[h] {
+                    HeapCellValue::Integer(ref arity) => {
+                        arity.to_usize().unwrap()
+                    }
+                    HeapCellValue::Addr(Addr::Fixnum(arity)) => {
+                        usize::try_from(*arity).unwrap()
+                    }
+                    _ => {
+                        unreachable!()
+                    }
+                }
             _ => unreachable!(),
         };
 
@@ -260,7 +274,7 @@ impl Machine {
                     if addrs.is_empty() {
                         self.make_undefined(name.clone(), arity);
                     }
-                    
+
                     self.print_new_dynamic_clause(addrs, name.clone(), arity)
                 }
                 Err(err) => {
@@ -280,12 +294,19 @@ impl Machine {
     fn retract_from_dynamic_predicate(&mut self) {
         let index = self.machine_st[temp_v!(3)].clone();
         let index = match self.machine_st.store(self.machine_st.deref(index)) {
-            Addr::Con(h) =>
-                if let HeapCellValue::Integer(n) = &self.machine_st.heap[h] {
-                    n.to_usize().unwrap()
-                } else {
-                    unreachable!()
-                },
+            Addr::Con(h) => {
+                match &self.machine_st.heap[h] {
+                    HeapCellValue::Integer(ref arity) => {
+                        arity.to_usize().unwrap()
+                    }
+                    HeapCellValue::Addr(Addr::Fixnum(arity)) => {
+                        usize::try_from(*arity).unwrap()
+                    }
+                    _ => {
+                        unreachable!()
+                    }
+                }
+            }
             _ => {
                 unreachable!()
             }
@@ -302,7 +323,7 @@ impl Machine {
                 if addrs.is_empty() {
                     self.make_undefined(name.clone(), arity);
                 }
-                 
+
                 self.print_new_dynamic_clause(addrs, name.clone(), arity)
             }
             Err(err) => {
index f979d38a5ab3bbff98efff433464a6cd49181ef4..3eeb48531edff1640982167af99dda5737d950a5 100644 (file)
@@ -6,6 +6,7 @@ use crate::prolog::machine::machine_indices::*;
 use crate::prolog::machine::partial_string::*;
 use crate::prolog::machine::raw_block::*;
 
+use std::convert::TryFrom;
 use std::mem;
 use std::ops::{Index, IndexMut};
 use std::ptr;
@@ -202,6 +203,9 @@ impl<T: RawBlockTraits> HeapTemplate<T> {
             Constant::EmptyList => {
                 Addr::EmptyList
             }
+            Constant::Fixnum(n) => {
+                Addr::Fixnum(n)
+            }
             Constant::Integer(n) => {
                 Addr::Con(self.push(HeapCellValue::Integer(n)))
             }
@@ -252,26 +256,6 @@ impl<T: RawBlockTraits> HeapTemplate<T> {
         h
     }
 
-    #[inline]
-    pub(crate)
-    fn rational_at(&self, h: usize) -> bool {
-        if let HeapCellValue::Rational(_) = &self[h] {
-            true
-        } else {
-            false
-        }
-    }
-
-    #[inline]
-    pub(crate)
-    fn integer_at(&self, h: usize) -> bool {
-        if let HeapCellValue::Integer(_) = &self[h] {
-            true
-        } else {
-            false
-        }
-    }
-
     #[inline]
     pub(crate)
     fn atom_at(&self, h: usize) -> bool {
@@ -475,6 +459,7 @@ impl<T: RawBlockTraits> HeapTemplate<T> {
     fn to_local_code_ptr(&self, addr: &Addr) -> Option<LocalCodePtr> {
         let extract_integer = |s: usize| -> Option<usize> {
             match &self[s] {
+                &HeapCellValue::Addr(Addr::Fixnum(n)) => usize::try_from(n).ok(),
                 &HeapCellValue::Integer(ref n) => n.to_usize(),
                 _ => None
             }
index c5fc505a347964aeb8050f24d72beaade0d4b573..5718fddd802828f298dbcb511d2dcb0e58ea3af2 100644 (file)
@@ -20,6 +20,7 @@ use indexmap::IndexMap;
 use std::cell::RefCell;
 use std::cmp::Ordering;
 use std::collections::{BTreeMap, VecDeque};
+use std::convert::TryFrom;
 use std::mem;
 use std::ops::{Add, AddAssign, Sub, SubAssign};
 use std::rc::Rc;
@@ -59,6 +60,7 @@ pub enum Addr {
     Con(usize),
     CutPoint(usize),
     EmptyList,
+    Fixnum(isize),
     Float(OrderedFloat<f64>),
     Lis(usize),
     HeapCell(usize),
@@ -155,8 +157,9 @@ impl Addr {
     #[inline]
     pub fn is_heap_bound(&self) -> bool {
         match self {
-            Addr::Char(_) | Addr::CharCode(_) | Addr::EmptyList
-          | Addr::CutPoint(_) | Addr::Usize(_) | Addr::Float(_) => {
+            Addr::Char(_) | Addr::CharCode(_) | Addr::EmptyList |
+            Addr::CutPoint(_) | Addr::Usize(_) | Addr::Fixnum(_) |
+            Addr::Float(_) => {
                 false
             }
             _ => {
@@ -189,44 +192,48 @@ impl Addr {
 
     pub(super)
     fn order_category(&self, heap: &Heap) -> Option<TermOrderCategory> {
-        match self {
-            Addr::HeapCell(_) | Addr::AttrVar(_) | Addr::StackCell(..) => {
-                Some(TermOrderCategory::Variable)
+        match Number::try_from((*self, heap)) {
+            Ok(Number::Integer(_)) | Ok(Number::Fixnum(_)) | Ok(Number::Rational(_)) => {
+                Some(TermOrderCategory::Integer)
             }
-            Addr::Float(_) => {
+            Ok(Number::Float(_)) => {
                 Some(TermOrderCategory::FloatingPoint)
             }
-            &Addr::Con(h) => {
-                match &heap[h] {
-                    HeapCellValue::Atom(..) => {
+            _ => {
+                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)
                     }
-                    HeapCellValue::Integer(_) => {
+                    Addr::CharCode(_) | Addr::Fixnum(_) | Addr::Usize(_) => {
                         Some(TermOrderCategory::Integer)
                     }
-                    HeapCellValue::Rational(_) => {
-                        Some(TermOrderCategory::Integer)
+                    Addr::Lis(_) | Addr::PStrLocation(..) | Addr::Str(_) => {
+                        Some(TermOrderCategory::Compound)
                     }
-                    HeapCellValue::DBRef(_) => {
+                    Addr::CutPoint(_) | Addr::Stream(_) => {
                         None
                     }
-                    _ => {
-                        unreachable!()
-                    }
                 }
             }
-            Addr::Char(_) | Addr::EmptyList => {
-                Some(TermOrderCategory::Atom)
-            }
-            Addr::Usize(_) | Addr::CharCode(_) => {
-                Some(TermOrderCategory::Integer)
-            }
-            Addr::Lis(_) | Addr::PStrLocation(..) | Addr::Str(_) => {
-                Some(TermOrderCategory::Compound)
-            }
-            Addr::CutPoint(_) | Addr::Stream(_) => {
-                None
-            }
         }
     }
 
@@ -257,13 +264,16 @@ impl Addr {
             &Addr::EmptyList => {
                 Some(Constant::EmptyList)
             }
+            &Addr::Fixnum(n) => {
+                Some(Constant::Fixnum(n))
+            }
             &Addr::Float(f) => {
                 Some(Constant::Float(f))
             }
             &Addr::PStrLocation(h, n) => {
                 let mut heap_pstr_iter =
                     machine_st.heap_pstr_iter(Addr::PStrLocation(h, n));
-                
+
                 let mut buf = String::new();
 
                 while let Some(Some(c)) = heap_pstr_iter.next() {
index f5077d9dbfd8bd1c3370803dd3ef8223942ce056..9ab9002f85b00922ea4110590ed94cccf34a2185 100644 (file)
@@ -56,7 +56,7 @@ impl<'a> Iterator for HeapPStrIter<'a> {
         } else {
             return None;
         }
-        
+
         match addr {
             Addr::PStrLocation(h, n) => {
                 if let &HeapCellValue::PartialString(ref pstr, _) = &self.machine_st.heap[h] {
@@ -72,7 +72,7 @@ impl<'a> Iterator for HeapPStrIter<'a> {
             }
             Addr::Lis(l) => {
                 let addr = self.machine_st.store(self.machine_st.deref(Addr::HeapCell(l)));
-                
+
                 if let Addr::Char(c) = addr {
                     self.focus = Addr::HeapCell(l + 1);
                     return Some(Some(c));
@@ -96,7 +96,7 @@ pub(super)
 fn compare_pstr<'a>(
     pstr_iter: HeapPStrIter<'a>,
     mut c_iter: impl Iterator<Item = char>,
-) -> bool {    
+) -> bool {
     for opt_c in pstr_iter {
         match opt_c {
             Some(_) => {
@@ -965,7 +965,7 @@ pub(crate) trait CallPolicy: Any {
                 let a1 = machine_st[r];
                 let n2 = machine_st.get_number(at)?;
 
-                let n2 = Addr::Con(machine_st.heap.push(n2.into()));
+                let n2 = machine_st.heap.put_constant(n2.into());
                 machine_st.unify(a1, n2);
 
                 return_from_clause!(machine_st.last_call, machine_st)
index b7c56b7873e603cb6ce5b856bd7b72f221507cb3..120e39f8acc9935078d5982e81cc360c9984c320 100644 (file)
@@ -21,6 +21,7 @@ use crate::prolog::rug::Integer;
 use indexmap::{IndexMap, IndexSet};
 
 use std::cmp::Ordering;
+use std::convert::TryFrom;
 use std::rc::Rc;
 
 macro_rules! try_or_fail {
@@ -261,8 +262,8 @@ impl MachineState {
 
                         self.fail = true;
                     }
-                    (Addr::PStrLocation(h, n), Addr::Lis(l))
-                  | (Addr::Lis(l), Addr::PStrLocation(h, n)) => {
+                    (Addr::PStrLocation(h, n), Addr::Lis(l)) |
+                    (Addr::Lis(l), Addr::PStrLocation(h, n)) => {
                         if let HeapCellValue::PartialString(ref pstr, _) = &self.heap[h] {
                             if let Some(c) = pstr.range_from(n ..).next() {
                                 pdl.push(Addr::PStrLocation(h, n + c.len_utf8()));
@@ -369,16 +370,17 @@ impl MachineState {
                             ) if db_ref_1 == db_ref_2 => {
                             }
                             (
-                                &HeapCellValue::Integer(ref n1),
-                                &HeapCellValue::Integer(ref n2),
-                            ) if &**n1 == &**n2 => {
-                            }
-                            (
-                                &HeapCellValue::Rational(ref n1),
-                                &HeapCellValue::Rational(ref n2),
-                            ) if &**n1 == &**n2 => {
-                            }
-                            _ => {
+                                v1,
+                                v2,
+                            ) => {
+                                if let Ok(n1) = Number::try_from(v1) {
+                                    if let Ok(n2) = Number::try_from(v2) {
+                                        if n1 == n2 {
+                                            continue;
+                                        }
+                                    }
+                                }
+
                                 self.fail = true;
                             }
                         }
@@ -397,10 +399,15 @@ 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 {
+                    (Addr::Stream(s1), Addr::Stream(s2)) => {
+                        if s1 != s2 {
+                            self.fail = true;
+                        }
+                    }
+                    (v, Addr::Con(h)) | (Addr::Con(h), v) => {
+                        if let Ok(n1) = Number::try_from(&self.heap[h]) {
+                            if let Ok(v) = Number::try_from(&HeapCellValue::Addr(v)) {
+                                if n1 == v {
                                     continue;
                                 }
                             }
@@ -408,23 +415,15 @@ impl MachineState {
 
                         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() {
+                    (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;
                                 }
                             }
                         }
 
-                        self.fail = true;
-                    }
-                    (Addr::Stream(s1), Addr::Stream(s2)) => {
-                        if s1 != s2 {
-                            self.fail = true;
-                        }
-                    }
-                    (a1, a2) => {
                         if a1 != a2 {
                             self.fail = true;
                         }
@@ -481,8 +480,8 @@ impl MachineState {
 
                         self.fail = true;
                     }
-                    (Addr::PStrLocation(h, n), Addr::Lis(l))
-                  | (Addr::Lis(l), Addr::PStrLocation(h, n)) => {
+                    (Addr::PStrLocation(h, n), Addr::Lis(l)) |
+                    (Addr::Lis(l), Addr::PStrLocation(h, n)) => {
                       if let HeapCellValue::PartialString(ref pstr, _) = &self.heap[h] {
                           if let Some(c) = pstr.range_from(n ..).next() {
                               pdl.push(Addr::PStrLocation(h, n + c.len_utf8()));
@@ -585,16 +584,17 @@ impl MachineState {
                             ) if db_ref_1 == db_ref_2 => {
                             }
                             (
-                                &HeapCellValue::Integer(ref n1),
-                                &HeapCellValue::Integer(ref n2),
-                            ) if &**n1 == &**n2 => {
-                            }
-                            (
-                                &HeapCellValue::Rational(ref n1),
-                                &HeapCellValue::Rational(ref n2),
-                            ) if &**n1 == &**n2 => {
-                            }
-                            _ => {
+                                v1,
+                                v2,
+                            ) => {
+                                if let Ok(n1) = Number::try_from(v1) {
+                                    if let Ok(n2) = Number::try_from(v2) {
+                                        if n1 == n2 {
+                                            continue;
+                                        }
+                                    }
+                                }
+
                                 self.fail = true;
                             }
                         }
@@ -613,10 +613,15 @@ 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 {
+                    (Addr::Stream(s1), Addr::Stream(s2)) => {
+                        if s1 != s2 {
+                            self.fail = true;
+                        }
+                    }
+                    (v, Addr::Con(h)) | (Addr::Con(h), v) => {
+                        if let Ok(n1) = Number::try_from(&self.heap[h]) {
+                            if let Ok(v) = Number::try_from(&HeapCellValue::Addr(v)) {
+                                if n1 == v {
                                     continue;
                                 }
                             }
@@ -624,23 +629,15 @@ impl MachineState {
 
                         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() {
+                    (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;
                                 }
                             }
                         }
 
-                        self.fail = true;
-                    }
-                    (Addr::Stream(s1), Addr::Stream(s2)) => {
-                        if s1 != s2 {
-                            self.fail = true;
-                        }
-                    }
-                    (a1, a2) => {
                         if a1 != a2 {
                             self.fail = true;
                         }
@@ -791,6 +788,9 @@ impl MachineState {
                     }
                     HeapCellValue::Integer(ref n1) => {
                         match c {
+                            Constant::Fixnum(n2) => {
+                                n1.to_isize() != Some(*n2)
+                            }
                             Constant::Integer(ref n2) => {
                                 n1 != n2
                             }
@@ -919,8 +919,7 @@ impl MachineState {
                 let n1 = try_or_fail!(self, self.get_number(a1));
                 let n2 = try_or_fail!(self, self.get_number(a2));
 
-                self.interms[t - 1] =
-                    Number::Integer(Rc::new(try_or_fail!(self, self.gcd(n1, n2))));
+                self.interms[t - 1] = try_or_fail!(self, self.gcd(n1, n2));
                 self.p += 1;
             }
             &ArithmeticInstruction::Pow(ref a1, ref a2, t) => {
@@ -944,16 +943,14 @@ impl MachineState {
                 let n1 = try_or_fail!(self, self.get_number(a1));
                 let n2 = try_or_fail!(self, self.get_number(a2));
 
-                self.interms[t - 1] =
-                    Number::Integer(Rc::new(try_or_fail!(self, self.int_floor_div(n1, n2))));
+                self.interms[t - 1] = try_or_fail!(self, self.int_floor_div(n1, n2));
                 self.p += 1;
             }
             &ArithmeticInstruction::IDiv(ref a1, ref a2, t) => {
                 let n1 = try_or_fail!(self, self.get_number(a1));
                 let n2 = try_or_fail!(self, self.get_number(a2));
 
-                self.interms[t - 1] =
-                    Number::Integer(Rc::new(try_or_fail!(self, self.idiv(n1, n2))));
+                self.interms[t - 1] = try_or_fail!(self, self.idiv(n1, n2));
                 self.p += 1;
             }
             &ArithmeticInstruction::Abs(ref a1, t) => {
@@ -965,7 +962,7 @@ impl MachineState {
             &ArithmeticInstruction::Sign(ref a1, t) => {
                 let n = try_or_fail!(self, self.get_number(a1));
 
-                self.interms[t - 1] = Number::Integer(Rc::new(self.sign(n)));
+                self.interms[t - 1] = self.sign(n);
                 self.p += 1;
             }
             &ArithmeticInstruction::Neg(ref a1, t) => {
@@ -977,8 +974,7 @@ impl MachineState {
             &ArithmeticInstruction::BitwiseComplement(ref a1, t) => {
                 let n1 = try_or_fail!(self, self.get_number(a1));
 
-                self.interms[t - 1] =
-                   Number::Integer(Rc::new(try_or_fail!(self, self.bitwise_complement(n1))));
+                self.interms[t - 1] = try_or_fail!(self, self.bitwise_complement(n1));
                 self.p += 1;
             }
             &ArithmeticInstruction::Div(ref a1, ref a2, t) => {
@@ -992,56 +988,49 @@ impl MachineState {
                 let n1 = try_or_fail!(self, self.get_number(a1));
                 let n2 = try_or_fail!(self, self.get_number(a2));
 
-                self.interms[t - 1] =
-                   Number::Integer(Rc::new(try_or_fail!(self, self.shr(n1, n2))));
+                self.interms[t - 1] = try_or_fail!(self, self.shr(n1, n2));
                 self.p += 1;
             }
             &ArithmeticInstruction::Shl(ref a1, ref a2, t) => {
                 let n1 = try_or_fail!(self, self.get_number(a1));
                 let n2 = try_or_fail!(self, self.get_number(a2));
 
-                self.interms[t - 1] =
-                   Number::Integer(Rc::new(try_or_fail!(self, self.shl(n1, n2))));
+                self.interms[t - 1] = try_or_fail!(self, self.shl(n1, n2));
                 self.p += 1;
             }
             &ArithmeticInstruction::Xor(ref a1, ref a2, t) => {
                 let n1 = try_or_fail!(self, self.get_number(a1));
                 let n2 = try_or_fail!(self, self.get_number(a2));
 
-                self.interms[t - 1] =
-       Number::Integer(Rc::new(try_or_fail!(self, self.xor(n1, n2))));
+                self.interms[t - 1] = try_or_fail!(self, self.xor(n1, n2));
                 self.p += 1;
             }
             &ArithmeticInstruction::And(ref a1, ref a2, t) => {
                 let n1 = try_or_fail!(self, self.get_number(a1));
                 let n2 = try_or_fail!(self, self.get_number(a2));
 
-                self.interms[t - 1] =
-                   Number::Integer(Rc::new(try_or_fail!(self, self.and(n1, n2))));
+                self.interms[t - 1] = try_or_fail!(self, self.and(n1, n2));
                 self.p += 1;
             }
             &ArithmeticInstruction::Or(ref a1, ref a2, t) => {
                 let n1 = try_or_fail!(self, self.get_number(a1));
                 let n2 = try_or_fail!(self, self.get_number(a2));
 
-                self.interms[t - 1] =
-       Number::Integer(Rc::new(try_or_fail!(self, self.or(n1, n2))));
+                self.interms[t - 1] = try_or_fail!(self, self.or(n1, n2));
                 self.p += 1;
             }
             &ArithmeticInstruction::Mod(ref a1, ref a2, t) => {
                 let n1 = try_or_fail!(self, self.get_number(a1));
                 let n2 = try_or_fail!(self, self.get_number(a2));
 
-                self.interms[t - 1] =
-       Number::Integer(Rc::new(try_or_fail!(self, self.modulus(n1, n2))));
+                self.interms[t - 1] = try_or_fail!(self, self.modulus(n1, n2));
                 self.p += 1;
             }
             &ArithmeticInstruction::Rem(ref a1, ref a2, t) => {
                 let n1 = try_or_fail!(self, self.get_number(a1));
                 let n2 = try_or_fail!(self, self.get_number(a2));
 
-                self.interms[t - 1] =
-       Number::Integer(Rc::new(try_or_fail!(self, self.remainder(n1, n2))));
+                self.interms[t - 1] = try_or_fail!(self, self.remainder(n1, n2));
                 self.p += 1;
             }
             &ArithmeticInstruction::Cos(ref a1, t) => {
@@ -1120,29 +1109,25 @@ impl MachineState {
             &ArithmeticInstruction::Truncate(ref a1, t) => {
                 let n1 = try_or_fail!(self, self.get_number(a1));
 
-                self.interms[t - 1] =
-                   Number::Integer(Rc::new(self.truncate(n1)));
+                self.interms[t - 1] = self.truncate(n1);
                 self.p += 1;
             }
             &ArithmeticInstruction::Round(ref a1, t) => {
                 let n1 = try_or_fail!(self, self.get_number(a1));
 
-                self.interms[t - 1] =
-                   Number::Integer(Rc::new(try_or_fail!(self, self.round(n1))));
+                self.interms[t - 1] = try_or_fail!(self, self.round(n1));
                 self.p += 1;
             }
             &ArithmeticInstruction::Ceiling(ref a1, t) => {
                 let n1 = try_or_fail!(self, self.get_number(a1));
 
-                self.interms[t - 1] =
-                   Number::Integer(Rc::new(self.ceiling(n1)));
+                self.interms[t - 1] = self.ceiling(n1);
                 self.p += 1;
             }
             &ArithmeticInstruction::Floor(ref a1, t) => {
                 let n1 = try_or_fail!(self, self.get_number(a1));
 
-                self.interms[t - 1] =
-                   Number::Integer(Rc::new(self.floor(n1)));
+                self.interms[t - 1] = self.floor(n1);
                 self.p += 1;
             }
             &ArithmeticInstruction::Plus(ref a1, t) => {
@@ -1332,7 +1317,7 @@ impl MachineState {
                         }
                     }
                     Addr::Char(_) | Addr::CharCode(_) | Addr::Con(_) | Addr::CutPoint(_) |
-                    Addr::EmptyList | Addr::Float(_) | Addr::Usize(_) => {
+                    Addr::EmptyList | Addr::Fixnum(_) | Addr::Float(_) | Addr::Usize(_) => {
                         c
                     }
                     Addr::Lis(_) => {
@@ -1624,19 +1609,35 @@ impl MachineState {
             Addr::HeapCell(_) | Addr::StackCell(..) => { // 8.5.2.3 a)
                 return Err(self.error_form(MachineError::instantiation_error(), stub))
             }
-            Addr::Con(h) => {
-                if let HeapCellValue::Integer(n) = self.heap.clone(h) {
-                    if &*n < &0 { // 8.5.2.3 e)
-                        let n = Number::Integer(n);
-                        let dom_err = MachineError::domain_error(
-                            DomainErrorType::NotLessThanZero,
-                            n,
-                        );
+            addr => {
+                let n =
+                    match Number::try_from((addr, &self.heap)) {
+                        Ok(Number::Fixnum(n))  => Integer::from(n),
+                        Ok(Number::Integer(n)) => Integer::from(n.as_ref()),
+                        _ => {
+                            return Err(self.error_form(
+                                MachineError::type_error(
+                                    self.heap.h(),
+                                    ValidType::Integer,
+                                    addr,
+                                ),
+                                stub,
+                            ));
+                        }
+                    };
 
-                        return Err(self.error_form(dom_err, stub));
-                    }
+                if n < 0 { // 8.5.2.3 e)
+                    let n = Number::from(n);
+                    let dom_err = MachineError::domain_error(
+                        DomainErrorType::NotLessThanZero,
+                        n,
+                    );
 
-                    let n = match n.to_usize() {
+                    return Err(self.error_form(dom_err, stub));
+                }
+
+                let n =
+                    match n.to_usize() {
                         Some(n) => n,
                         None => {
                             self.fail = true;
@@ -1644,88 +1645,68 @@ impl MachineState {
                         }
                     };
 
-                    let term = self.store(self.deref(self[temp_v!(2)]));
+                let term = self.store(self.deref(self[temp_v!(2)]));
 
-                    match term {
-                        Addr::HeapCell(_) | Addr::StackCell(..) => { // 8.5.2.3 b)
-                            return Err(self.error_form(MachineError::instantiation_error(), stub))
-                        }
-                        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);
+                match term {
+                    Addr::HeapCell(_) | Addr::StackCell(..) | Addr::AttrVar(_) => { // 8.5.2.3 b)
+                        return Err(self.error_form(MachineError::instantiation_error(), stub))
+                    }
+                    Addr::Str(o) => match self.heap.clone(o) {
+                        HeapCellValue::NamedStr(arity, _, _) if 1 <= n && n <= arity => {
+                            let a3 = self[temp_v!(3)];
+                            let h_a = Addr::HeapCell(o + n);
 
-                                self.unify(a3, h_a);
-                            }
-                            _ => {
-                                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);
+                        }
+                        _ => {
+                            self.fail = true;
+                        }
+                    },
+                    Addr::Lis(l) => {
+                        if n == 1 || n == 2 {
+                            let a3 = self[temp_v!(3)];
+                            let h_a = Addr::HeapCell(l + n - 1);
 
-                                self.unify(a3, h_a);
-                            } else {
-                                self.fail = true;
-                            }
+                            self.unify(a3, h_a);
+                        } else {
+                            self.fail = true;
                         }
-                        Addr::PStrLocation(h, offset) => {
-                            if n == 1 || n == 2 {
-                                let a3 = self[temp_v!(3)];
-                                let h_a =
-                                    if let HeapCellValue::PartialString(ref pstr, _) = &self.heap[h] {
-                                        if let Some(c) = pstr.range_from(offset ..).next() {
-                                            if n == 1 {
-                                                Addr::Char(c)
-                                            } else {
-                                                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 {
-                                            unreachable!()
+                                            Addr::PStrLocation(h, offset + c.len_utf8())
                                         }
                                     } else {
                                         unreachable!()
-                                    };
+                                    }
+                                } else {
+                                    unreachable!()
+                                };
 
-                                self.unify(a3, h_a);
-                            } else {
-                                self.fail = true;
-                            }
-                        }
-                        _ => { // 8.5.2.3 d)
-                            return Err(self.error_form(
-                                MachineError::type_error(
-                                    self.heap.h(),
-                                    ValidType::Compound,
-                                    term,
-                                ),
-                                stub,
-                            ))
+                            self.unify(a3, h_a);
+                        } else {
+                            self.fail = true;
                         }
                     }
-                } else {
-                    return Err(self.error_form(
-                        MachineError::type_error(
-                            self.heap.h(),
-                            ValidType::Integer,
-                            Addr::HeapCell(h),
-                        ),
-                        stub,
-                    ))
+                    _ => { // 8.5.2.3 d)
+                        return Err(self.error_form(
+                            MachineError::type_error(
+                                self.heap.h(),
+                                ValidType::Compound,
+                                term,
+                            ),
+                            stub,
+                        ))
+                    }
                 }
             }
-            _ => { // 8.5.2.3 c)
-                return Err(self.error_form(
-                    MachineError::type_error(
-                        self.heap.h(),
-                        ValidType::Integer,
-                        n,
-                    ),
-                    stub,
-                ))
-            }
         }
 
         Ok(())
@@ -1747,7 +1728,8 @@ impl MachineState {
         self.p += 1;
     }
 
-    pub(super) fn compare_term(&mut self, qt: CompareTermQT) {
+    pub(super)
+    fn compare_term(&mut self, qt: CompareTermQT) {
         let a1 = self[temp_v!(1)];
         let a2 = self[temp_v!(2)];
 
@@ -1804,18 +1786,10 @@ impl MachineState {
                 (Addr::Con(h1), Addr::Con(h2)) => {
                     match (&self.heap[h1], &self.heap[h2]) {
                         (
-                            &HeapCellValue::Integer(ref n1),
-                            &HeapCellValue::Integer(ref n2),
-                        ) => {
-                            if n1 != n2 {
-                                return true;
-                            }
-                        }
-                        (
-                            &HeapCellValue::Rational(ref n1),
-                            &HeapCellValue::Rational(ref n2),
+                            &HeapCellValue::Atom(ref n1, ref spec_1),
+                            &HeapCellValue::Atom(ref n2, ref spec_2),
                         ) => {
-                            if n1 != n2 {
+                            if n1 != n2 || spec_1 != spec_2 {
                                 return true;
                             }
                         }
@@ -1828,14 +1802,17 @@ impl MachineState {
                             }
                         }
                         (
-                            &HeapCellValue::Atom(ref n1, ref spec_1),
-                            &HeapCellValue::Atom(ref n2, ref spec_2),
+                            v1,
+                            v2,
                         ) => {
-                            if n1 != n2 || spec_1 != spec_2 {
-                                return true;
+                            if let Ok(n1) = Number::try_from(v1) {
+                                if let Ok(n2) = Number::try_from(v2) {
+                                    if n1 == n2 {
+                                        continue;
+                                    }
+                                }
                             }
-                        }
-                        _ => {
+
                             return true;
                         }
                     }
@@ -1852,25 +1829,26 @@ impl MachineState {
                         }
                     }
                 }
-                (Addr::Usize(n1), Addr::Con(n2)) | (Addr::Con(n2), Addr::Usize(n1)) => {
-                    if let HeapCellValue::Integer(ref n2) = &self.heap[n2] {
-                        if let Some(n2) = n2.to_usize() {
+                (Addr::CharCode(n1), v2) | (v2, Addr::CharCode(n1)) => {
+                    if let Ok(n2) = Number::try_from((v2, &self.heap)) {
+                        if let Some(n2) = n2.to_u32() {
                             if n1 != n2 {
                                 return true;
                             }
                         }
                     }
                 }
-                (Addr::CharCode(n1), Addr::Con(n2)) | (Addr::Con(n2), Addr::CharCode(n1)) => {
-                    if let HeapCellValue::Integer(ref n2) = &self.heap[n2] {
-                        if let Some(n2) = n2.to_u32() {
-                            if n1 == n2 {
+                (a1, a2) => {
+                    if let Ok(n1) = Number::try_from((a1, &self.heap)) {
+                        if let Ok(n2) = Number::try_from((a2, &self.heap)) {
+                            if n1 != n2 {
                                 return true;
+                            } else {
+                                continue;
                             }
                         }
                     }
-                }
-                (a1, a2) => {
+
                     if a1 != a2 {
                         return true;
                     }
@@ -1919,75 +1897,63 @@ impl MachineState {
                             Addr::Con(h1),
                             Addr::Con(h2),
                         ) => {
-                            match (&self.heap[h1], &self.heap[h2]) {
-                                (
-                                    HeapCellValue::Integer(ref n1),
-                                    HeapCellValue::Integer(ref n2),
-                                ) => {
-                                    if &*n1 != &*n2 {
-                                        return Some(n1.cmp(&*n2));
-                                    }
-                                }
-                                (
-                                    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));
+                            if let Ok(n1) = Number::try_from(&self.heap[h1]) {
+                                if let Ok(n2) = Number::try_from(&self.heap[h2]) {
+                                    if n1 != n2 {
+                                        return Some(n1.cmp(&n2));
                                     }
-                                }
-                                _ => {
+                                } else {
                                     unreachable!()
                                 }
+                            } else {
+                                unreachable!()
                             }
                         }
-                        (Addr::Usize(n1), Addr::Usize(n2)) => {
-                            if n1 != n2 {
-                                return Some(n1.cmp(&n2));
-                            }
-                        }
-                        (Addr::CharCode(n1), Addr::CharCode(n2)) => {
-                            if n1 != n2 {
-                                return Some(n1.cmp(&n2));
+                        (
+                            Addr::Con(h1),
+                            v2,
+                        ) => {
+                            if let Ok(n1) = Number::try_from(&self.heap[h1]) {
+                                if let Ok(n2) = Number::try_from(&HeapCellValue::Addr(v2)) {
+                                    if n1 != n2 {
+                                        return Some(n1.cmp(&n2));
+                                    }
+                                } else {
+                                    unreachable!()
+                                }
+                            } else {
+                                unreachable!()
                             }
                         }
-                        (Addr::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() {
+                        (
+                            v1,
+                            Addr::Con(h2),
+                        ) => {
+                            if let Ok(n1) = Number::try_from(&HeapCellValue::Addr(v1)) {
+                                if let Ok(n2) = Number::try_from(&self.heap[h2]) {
                                     if n1 != n2 {
                                         return Some(n1.cmp(&n2));
                                     }
+                                } else {
+                                    unreachable!()
                                 }
+                            } else {
+                                unreachable!()
                             }
                         }
-                        (Addr::CharCode(n1), Addr::Con(n2)) | (Addr::Con(n2), Addr::CharCode(n1)) => {
-                            if let HeapCellValue::Integer(ref n2) = &self.heap[n2] {
-                                if let Some(n2) = n2.to_u32() {
+                        (v1, v2) => {
+                            if let Ok(n1) = Number::try_from(&HeapCellValue::Addr(v1)) {
+                                if let Ok(n2) = Number::try_from(&HeapCellValue::Addr(v2)) {
                                     if n1 != n2 {
                                         return Some(n1.cmp(&n2));
                                     }
+                                } else {
+                                    unreachable!()
                                 }
+                            } else {
+                                unreachable!()
                             }
                         }
-                        _ => {
-                            unreachable!()
-                        }
                     }
                 }
                 Some(TermOrderCategory::Atom) => {
@@ -2330,34 +2296,34 @@ impl MachineState {
             &InlinedClauseType::IsInteger(r1) => {
                 let d = self.store(self.deref(self[r1]));
 
-                match d {
-                    Addr::Con(h) => {
-                        match &self.heap[h] {
-                            HeapCellValue::Integer(_) => {
+                match Number::try_from((d, &self.heap)) {
+                    Ok(Number::Fixnum(_)) => {
+                        self.p += 1;
+                    }
+                    Ok(Number::Integer(_)) => {
+                        self.p += 1;
+                    }
+                    Ok(Number::Rational(n)) => {
+                        if n.denom() == &1 {
+                            self.p += 1;
+                        } else {
+                            self.fail = true;
+                        }
+                    }
+                    _ => {
+                        match d {
+                            Addr::CharCode(_) => {
                                 self.p += 1;
                             }
-                            HeapCellValue::Rational(ref r) => {
-                                if r.denom() == &1 {
-                                    self.p += 1;
-                                } else {
-                                    self.fail = true;
-                                }
+                            Addr::Char(_) if self.flags.double_quotes.is_codes() => {
+                                self.p += 1;
                             }
                             _ => {
                                 self.fail = true;
                             }
                         }
                     }
-                    Addr::CharCode(_) | Addr::Usize(_) => {
-                        self.p += 1;
-                    }
-                    Addr::Char(_) if self.flags.double_quotes.is_codes() => {
-                        self.p += 1;
-                    }
-                    _ => {
-                        self.fail = true;
-                    }
-                };
+                }
             }
             &InlinedClauseType::IsCompound(r1) => {
                 let d = self.store(self.deref(self[r1]));
@@ -2484,8 +2450,8 @@ impl MachineState {
             Addr::Stream(_) => {
                 self.fail = true;
             }
-            Addr::Char(_) | Addr::CharCode(_) | Addr::Con(_) | Addr::Float(_) |
-            Addr::EmptyList | Addr::Usize(_) => {
+            Addr::Char(_) | Addr::CharCode(_) | Addr::Con(_) | Addr::Fixnum(_) |
+            Addr::Float(_) | Addr::EmptyList | Addr::Usize(_) => {
                 self.try_functor_unify_components(a1, 0);
             }
             Addr::Str(o) => match self.heap.clone(o) {
@@ -2510,48 +2476,33 @@ impl MachineState {
                     return Err(self.error_form(MachineError::instantiation_error(), stub));
                 }
 
-                let arity = match arity {
-                    Addr::Con(h) => {
-                        match &self.heap[h] {
-                            &HeapCellValue::Integer(ref n) => {
-                                n.to_isize()
-                            }
-                            &HeapCellValue::Addr(Addr::Usize(n)) => {
-                                Some(n as isize)
-                            }
-                            _ => {
-                                return Err(
-                                    self.error_form(
-                                        MachineError::type_error(
-                                            self.heap.h(),
-                                            ValidType::Integer,
-                                            arity,
-                                        ),
-                                        stub,
-                                    )
-                                );
+                let arity =
+                    match Number::try_from((arity, &self.heap)) {
+                        Ok(Number::Fixnum(n))  => Some(n),
+                        Ok(Number::Integer(n)) => n.to_isize(),
+                        Ok(Number::Rational(n))
+                            if n.denom() == &1 => {
+                                n.numer().to_isize()
+                            },
+                        _ =>
+                            match arity {
+                                Addr::CharCode(c) => {
+                                    Some(c as isize)
+                                }
+                                arity => {
+                                    return Err(
+                                        self.error_form(
+                                            MachineError::type_error(
+                                                self.heap.h(),
+                                                ValidType::Integer,
+                                                arity,
+                                            ),
+                                            stub,
+                                        )
+                                    );
+                                }
                             }
-                        }
-                    },
-                    Addr::Usize(n) => {
-                        Some(n as isize)
-                    }
-                    Addr::CharCode(c) => {
-                        Some(c as isize)
-                    }
-                    arity => {
-                        return Err(
-                            self.error_form(
-                                MachineError::type_error(
-                                    self.heap.h(),
-                                    ValidType::Integer,
-                                    arity,
-                                ),
-                                stub,
-                            )
-                        );
-                    }
-                };
+                    };
 
                 let arity = match arity {
                     Some(arity) => {
@@ -2579,7 +2530,7 @@ impl MachineState {
                 }
 
                 match name {
-                    Addr::Char(_) | Addr::CharCode(_) | Addr::Con(_) | Addr::Float(_) |
+                    Addr::Char(_) | Addr::CharCode(_) | Addr::Con(_) | Addr::Fixnum(_) | Addr::Float(_) |
                     Addr::EmptyList | Addr::PStrLocation(..) | Addr::Usize(_) if arity == 0 => {
                         self.unify(a1, name);
                     }
@@ -2925,34 +2876,6 @@ impl MachineState {
                     HeapCellValue::Addr(Addr::PStrLocation(..)),
                 ) => {
                 }
-                (
-                    HeapCellValue::Integer(n1),
-                    HeapCellValue::Integer(n2),
-                ) => {
-                    if &*n1 != &*n2 {
-                        return true;
-                    }
-                }
-                (
-                    HeapCellValue::Rational(n1),
-                    HeapCellValue::Rational(n2),
-                ) => {
-                    if &*n1 != &*n2 {
-                        return true;
-                    }
-                }
-                (
-                    HeapCellValue::Integer(ref n1),
-                    HeapCellValue::Rational(ref n2),
-                ) |
-                (
-                    HeapCellValue::Rational(ref n2),
-                    HeapCellValue::Integer(ref n1),
-                ) => {
-                    if n1.as_ref().partial_cmp(&**n2) == Some(Ordering::Equal) {
-                        return true;
-                    }
-                }
                 (
                     HeapCellValue::Atom(ref n1, ref spec_1),
                     HeapCellValue::Atom(ref n2, ref spec_2),
@@ -2970,15 +2893,34 @@ impl MachineState {
                     }
                 }
                 (
-                    HeapCellValue::Addr(a1),
-                    HeapCellValue::Addr(a2),
+                    v1,
+                    v2,
                 ) => {
-                    if a1 != a2 {
-                        return true;
+                    if let Ok(n1) = Number::try_from(v1) {
+                        if let Ok(n2) = Number::try_from(v2) {
+                            if n1 != n2 {
+                                return true;
+                            } else {
+                                continue;
+                            }
+                        } else {
+                            return true;
+                        }
+                    }
+
+                    match (v1, v2) {
+                        (
+                            HeapCellValue::Addr(a1),
+                            HeapCellValue::Addr(a2),
+                        ) => {
+                            if a1 != a2 {
+                                return true;
+                            }
+                        }
+                        _ => {
+                            return true;
+                        }
                     }
-                }
-                _ => {
-                    return true;
                 }
             }
         }
@@ -3051,13 +2993,13 @@ impl MachineState {
         lco: bool,
         use_default_cp: bool,
     ) {
-       let interrupted = INTERRUPT.load(std::sync::atomic::Ordering::Relaxed);
+           let interrupted = INTERRUPT.load(std::sync::atomic::Ordering::Relaxed);
 
-       if INTERRUPT.compare_and_swap(interrupted, false, std::sync::atomic::Ordering::Relaxed) {
-           self.reset();
-           self.fail = true;
-           return;
-       }
+           if INTERRUPT.compare_and_swap(interrupted, false, std::sync::atomic::Ordering::Relaxed) {
+               self.reset();
+               self.fail = true;
+               return;
+           }
 
         let mut default_call_policy: Box<dyn CallPolicy> = Box::new(DefaultCallPolicy {});
 
@@ -3192,8 +3134,12 @@ impl MachineState {
                 self.hb = self.heap.h();
                 self.p += offset;
             }
-            &IndexedChoiceInstruction::Retry(l) => try_or_fail!(self, call_policy.retry(self, l)),
-            &IndexedChoiceInstruction::Trust(l) => try_or_fail!(self, call_policy.trust(self, l)),
+            &IndexedChoiceInstruction::Retry(l) => {
+                try_or_fail!(self, call_policy.retry(self, l));
+            }
+            &IndexedChoiceInstruction::Trust(l) => {
+                try_or_fail!(self, call_policy.trust(self, l));
+            }
         };
     }
 
@@ -3241,7 +3187,9 @@ impl MachineState {
             &ChoiceInstruction::RetryMeElse(offset) => {
                 try_or_fail!(self, call_policy.retry_me_else(self, offset))
             }
-            &ChoiceInstruction::TrustMe => try_or_fail!(self, call_policy.trust_me(self)),
+            &ChoiceInstruction::TrustMe => {
+                try_or_fail!(self, call_policy.trust_me(self))
+            }
         }
     }
 
index 7271c150bef064b550a9ec73b753dff3bc3ab2cb..4f859c5740151da3b6b3fa27b281817958bf111e 100644 (file)
@@ -45,6 +45,7 @@ use crate::prolog::machine::toplevel::*;
 use indexmap::IndexMap;
 
 use std::collections::VecDeque;
+use std::convert::TryFrom;
 use std::fs::File;
 use std::mem;
 use std::ops::Index;
@@ -205,11 +206,11 @@ impl SubModuleUser for IndexStore {
 #[inline]
 fn current_dir() -> std::path::PathBuf {
     let mut path_buf = std::path::PathBuf::from(PROJECT_DIR);
-    
+
     // file!() always produces a path relative to PROJECT_DIR.
     path_buf = path_buf.join(std::path::PathBuf::from(file!()));
 
-    path_buf.pop();    
+    path_buf.pop();
     path_buf
 }
 
@@ -322,34 +323,34 @@ impl Machine {
     }
 
     pub fn run_init_code(&mut self, code: Code) -> bool {
-       let old_machine_st = self.sink_to_snapshot();
-       self.machine_st.reset();
+           let old_machine_st = self.sink_to_snapshot();
+           self.machine_st.reset();
 
-       self.code_repo.cached_query = code;
-       self.run_query();
+           self.code_repo.cached_query = code;
+           self.run_query();
 
         let result = self.machine_st.fail;
-       self.absorb_snapshot(old_machine_st);
+           self.absorb_snapshot(old_machine_st);
 
         !result
     }
 
     pub fn run_top_level(&mut self) {
-       use std::env;
+           use std::env;
 
-       let mut filename_atoms = vec![];
+           let mut filename_atoms = vec![];
 
-       // the first of these is the path to the scryer-prolog executable, so skip
-       // it.
-       for filename in env::args().skip(1) {
-           let atom = clause_name!(filename, self.indices.atom_tbl);
-           filename_atoms.push(HeapCellValue::Atom(atom, None));
-       }
+           // the first of these is the path to the scryer-prolog executable, so skip
+           // it.
+           for filename in env::args().skip(1) {
+               let atom = clause_name!(filename, self.indices.atom_tbl);
+               filename_atoms.push(HeapCellValue::Atom(atom, None));
+           }
 
-       let list_addr =
-           Addr::HeapCell(self.machine_st.heap.to_list(filename_atoms.into_iter()));
+           let list_addr =
+               Addr::HeapCell(self.machine_st.heap.to_list(filename_atoms.into_iter()));
 
-       self.machine_st[temp_v!(1)] = list_addr;
+           self.machine_st[temp_v!(1)] = list_addr;
         self.machine_st.p = CodePtr::Local(LocalCodePtr::DirEntry(self.toplevel_idx));
 
         self.run_query();
@@ -397,7 +398,7 @@ impl Machine {
                                 lib_path.clone(),
                             )
         );
-        
+
         compile_user_module(&mut wam,
                             Stream::from(LISTS),
                             true,
@@ -406,7 +407,7 @@ impl Machine {
                                 lib_path.clone(),
                             ),
         );
-        
+
         compile_user_module(&mut wam,
                             Stream::from(ISO_EXT),
                             true,
@@ -415,7 +416,7 @@ impl Machine {
                                 lib_path.clone(),
                             )
         );
-        
+
         compile_user_module(&mut wam,
                             Stream::from(SI),
                             true,
@@ -539,53 +540,57 @@ impl Machine {
 
     fn extract_module_export_list(&mut self) -> Result<Vec<ModuleExport>, ParserError>
     {
-       let mut export_list = self.machine_st[temp_v!(2)].clone();
-       let mut exports = vec![];
+           let mut export_list = self.machine_st[temp_v!(2)].clone();
+           let mut exports = vec![];
 
-       while let Addr::Lis(l) = self.machine_st.store(self.machine_st.deref(export_list)) {
-           match &self.machine_st.heap[l] {
-               &HeapCellValue::Addr(Addr::Str(s)) => {
+           while let Addr::Lis(l) = self.machine_st.store(self.machine_st.deref(export_list)) {
+               match &self.machine_st.heap[l] {
+                       &HeapCellValue::Addr(Addr::Str(s)) => {
                     match &self.machine_st.heap[s] {
                         HeapCellValue::NamedStr(arity, ref name, _)
                             if *arity == 2 && name.as_str() == "/" => {
-                               let name = match &self.machine_st.heap[s+1] {
-                                   &HeapCellValue::Atom(ref name, _) =>
-                                       name.clone(),
-                                   _ =>
-                                       unreachable!()
-                               };
-
-                               let arity = match &self.machine_st.heap[s+2] {
-                                   &HeapCellValue::Integer(ref arity) =>
-                                       arity.to_usize().unwrap(),
-                                   _ =>
-                                       unreachable!()
-                               };
-
-                               exports.push(ModuleExport::PredicateKey((name, arity)));
+                                       let name = match &self.machine_st.heap[s+1] {
+                                               &HeapCellValue::Atom(ref name, _) =>
+                                                   name.clone(),
+                                               _ =>
+                                                   unreachable!()
+                                       };
+
+                                       let arity = match &self.machine_st.heap[s+2] {
+                                               &HeapCellValue::Integer(ref arity) =>
+                                                   arity.to_usize().unwrap(),
+                                    &HeapCellValue::Addr(Addr::Fixnum(n)) =>
+                                        usize::try_from(n).unwrap(),
+                                               _ =>
+                                                   unreachable!()
+                                       };
+
+                                       exports.push(ModuleExport::PredicateKey((name, arity)));
                             }
                         HeapCellValue::NamedStr(arity, ref name, _)
                             if *arity == 3 && name.as_str() == "op" => {
                                 let name = match &self.machine_st.heap[s+3] {
-                                   &HeapCellValue::Atom(ref name, _) =>
-                                       name.clone(),
-                                   _ =>
-                                       unreachable!()
-                               };
+                                               &HeapCellValue::Atom(ref name, _) =>
+                                                   name.clone(),
+                                               _ =>
+                                                   unreachable!()
+                                       };
 
                                 let spec = match &self.machine_st.heap[s+2] {
-                                   &HeapCellValue::Atom(ref name, _) =>
-                                       name.clone(),
-                                   _ =>
-                                       unreachable!()
-                               };
-
-                               let prec = match &self.machine_st.heap[s+1] {
-                                   &HeapCellValue::Integer(ref arity) =>
-                                       arity.to_usize().unwrap(),
-                                   _ =>
-                                       unreachable!()
-                               };
+                                               &HeapCellValue::Atom(ref name, _) =>
+                                                   name.clone(),
+                                               _ =>
+                                                   unreachable!()
+                                       };
+
+                                       let prec = match &self.machine_st.heap[s+1] {
+                                               &HeapCellValue::Integer(ref arity) =>
+                                                   arity.to_usize().unwrap(),
+                                    &HeapCellValue::Addr(Addr::Fixnum(n)) =>
+                                        usize::try_from(n).unwrap(),
+                                               _ =>
+                                                   unreachable!()
+                                       };
 
                                 exports.push(ModuleExport::OpDecl(to_op_decl(
                                     prec,
@@ -595,47 +600,47 @@ impl Machine {
                             }
                         _ => unreachable!()
                     }
-               }
-               _ => unreachable!()
-           }
+                       }
+                       _ => unreachable!()
+               }
 
-           export_list = self.machine_st.heap[l+1].as_addr(l+1);
-       }
+               export_list = self.machine_st.heap[l+1].as_addr(l+1);
+           }
 
-       Ok(exports)
+           Ok(exports)
     }
 
     fn use_module<ToSource>(&mut self, to_src: ToSource)
        where ToSource: Fn(ClauseName) -> ModuleSource
     {
-       // the term expander will overwrite the cached query, so save it here.
-       let cached_query = mem::replace(&mut self.code_repo.cached_query, vec![]);
+           // the term expander will overwrite the cached query, so save it here.
+           let cached_query = mem::replace(&mut self.code_repo.cached_query, vec![]);
 
-       let module_spec = self.machine_st[temp_v!(1)].clone();
-       let name = {
+           let module_spec = self.machine_st[temp_v!(1)].clone();
+           let name = {
             let addr = self.machine_st.store(self.machine_st.deref(module_spec));
 
             match self.machine_st.heap.index_addr(&addr).as_ref() {
                 HeapCellValue::Atom(name, _) => name.clone(),
-               _ => unreachable!(),
+                   _ => unreachable!(),
             }
-       };
+           };
 
-       let load_result = match to_src(name) {
-           ModuleSource::Library(name) =>
+           let load_result = match to_src(name) {
+               ModuleSource::Library(name) =>
                 if let Some(module) = self.indices.take_module(name.clone()) {
                     self.indices.remove_module(clause_name!("user"), &module);
                     self.indices.modules.insert(name.clone(), module);
 
-                   Ok(name)
-               } else {
-                   load_library(self, name, false)
-               },
-           ModuleSource::File(name) =>
+                           Ok(name)
+                       } else {
+                           load_library(self, name, false)
+                       },
+               ModuleSource::File(name) =>
                 load_module_from_file(self, PathBuf::from(name.as_str()), false)
-       };
+           };
 
-       let result = load_result.and_then(|name| {
+           let result = load_result.and_then(|name| {
             let module = self.indices.take_module(name.clone()).unwrap();
 
             if !module.is_impromptu_module {
@@ -645,30 +650,30 @@ impl Machine {
             Ok(self.indices.insert_module(module))
         });
 
-       self.code_repo.cached_query = cached_query;
+           self.code_repo.cached_query = cached_query;
 
-       if let Err(e) = result {
-           self.throw_session_error(e, (clause_name!("use_module"), 1));
-       }
+           if let Err(e) = result {
+               self.throw_session_error(e, (clause_name!("use_module"), 1));
+           }
     }
 
     fn use_qualified_module<ToSource>(&mut self, to_src: ToSource)
        where ToSource: Fn(ClauseName) -> ModuleSource
     {
-       // the term expander will overwrite the cached query, so save it here.
-       let cached_query = mem::replace(&mut self.code_repo.cached_query, vec![]);
+           // the term expander will overwrite the cached query, so save it here.
+           let cached_query = mem::replace(&mut self.code_repo.cached_query, vec![]);
 
-       let module_spec = self.machine_st[temp_v!(1)].clone();
-       let name = {
+           let module_spec = self.machine_st[temp_v!(1)].clone();
+           let name = {
             let addr = self.machine_st.store(self.machine_st.deref(module_spec));
 
             match self.machine_st.heap.index_addr(&addr).as_ref() {
                 HeapCellValue::Atom(name, _) => name.clone(),
-               _ => unreachable!(),
+                   _ => unreachable!(),
             }
-       };
+           };
 
-       let exports = match self.extract_module_export_list() {
+           let exports = match self.extract_module_export_list() {
             Ok(exports) => exports,
             Err(e) => {
                 self.throw_session_error(SessionError::from(e), (clause_name!("use_module"), 2));
@@ -676,38 +681,38 @@ impl Machine {
             }
         };
 
-       let load_result = match to_src(name) {
-           ModuleSource::Library(name) =>
+           let load_result = match to_src(name) {
+               ModuleSource::Library(name) =>
                 if let Some(module) = self.indices.take_module(name.clone()) {
                     self.indices.remove_module(clause_name!("user"), &module);
                     self.indices.modules.insert(name.clone(), module);
 
-                   Ok(name)
-               } else {
-                   load_library(self, name, false)
-               },
-           ModuleSource::File(name) =>
+                           Ok(name)
+                       } else {
+                           load_library(self, name, false)
+                       },
+               ModuleSource::File(name) =>
                 load_module_from_file(self, PathBuf::from(name.as_str()), false)
-       };
+           };
 
-       let result = load_result.and_then(|name| {
-           let module = self.indices.take_module(name.clone()).unwrap();
+           let result = load_result.and_then(|name| {
+               let module = self.indices.take_module(name.clone()).unwrap();
 
             if !module.is_impromptu_module {
-               self.indices.use_qualified_module(&mut self.code_repo,
-                                                 self.machine_st.flags,
-                                                 &module,
-                                                 &exports)?;
+                   self.indices.use_qualified_module(&mut self.code_repo,
+                                                                     self.machine_st.flags,
+                                                                     &module,
+                                                                     &exports)?;
             }
 
-           Ok(self.indices.insert_module(module))
+               Ok(self.indices.insert_module(module))
         });
 
-       self.code_repo.cached_query = cached_query;
+           self.code_repo.cached_query = cached_query;
 
-       if let Err(e) = result {
-           self.throw_session_error(e, (clause_name!("use_module"), 2));
-       }
+           if let Err(e) = result {
+               self.throw_session_error(e, (clause_name!("use_module"), 2));
+           }
     }
 
     fn handle_toplevel_command(&mut self, code_ptr: REPLCodePtr, p: LocalCodePtr) {
@@ -722,14 +727,14 @@ impl Machine {
                     self.throw_session_error(e, (clause_name!("repl"), 0));
                 }
             }
-           REPLCodePtr::UseModule =>
-               self.use_module(ModuleSource::Library),
-           REPLCodePtr::UseModuleFromFile =>
-               self.use_module(ModuleSource::File),
-           REPLCodePtr::UseQualifiedModule =>
-               self.use_qualified_module(ModuleSource::Library),
-           REPLCodePtr::UseQualifiedModuleFromFile =>
-               self.use_qualified_module(ModuleSource::File)
+               REPLCodePtr::UseModule =>
+                       self.use_module(ModuleSource::Library),
+               REPLCodePtr::UseModuleFromFile =>
+                       self.use_module(ModuleSource::File),
+               REPLCodePtr::UseQualifiedModule =>
+                       self.use_qualified_module(ModuleSource::Library),
+               REPLCodePtr::UseQualifiedModuleFromFile =>
+                       self.use_qualified_module(ModuleSource::File)
         }
 
         self.machine_st.p = CodePtr::Local(p);
@@ -786,7 +791,7 @@ impl Machine {
     }
 
     pub(super) fn run_query(&mut self) {
-       self.machine_st.cp = LocalCodePtr::TopLevel(0, self.code_repo.size_of_cached_query());
+           self.machine_st.cp = LocalCodePtr::TopLevel(0, self.code_repo.size_of_cached_query());
         let end_ptr = CodePtr::Local(self.machine_st.cp);
 
         while self.machine_st.p < end_ptr {
index dbbc25e517654b1719303fb34d456122f1497024..b6e81a0930cf26a69d3e1ea89349c54f5b2f9e8b 100644 (file)
@@ -23,9 +23,9 @@ use crate::ref_thread_local::RefThreadLocal;
 use indexmap::{IndexMap, IndexSet};
 
 use std::cmp;
+use std::convert::TryFrom;
 use std::io::{stdout, Write};
 use std::iter::once;
-use std::mem;
 use std::rc::Rc;
 
 use crate::crossterm::event::{read, Event, KeyCode, KeyEvent};
@@ -269,9 +269,9 @@ impl MachineState {
         }
     }
 
-    fn skip_max_list_result(&mut self, max_steps: &Integer) {
+    fn skip_max_list_result(&mut self, max_steps: Option<isize>) {
         let search_result =
-            if let Some(max_steps) = max_steps.to_isize() {
+            if let Some(max_steps) = max_steps {
                 if max_steps == -1 {
                     self.detect_cycles(self[temp_v!(3)])
                 } else {
@@ -307,59 +307,66 @@ impl MachineState {
         };
     }
 
-    pub(super) fn skip_max_list(&mut self) -> CallResult {
+    pub(super)
+    fn skip_max_list(&mut self) -> CallResult {
         let max_steps = self.store(self.deref(self[temp_v!(2)]));
 
         match max_steps {
-            Addr::Con(h) if self.heap.integer_at(h) => {
-                if let HeapCellValue::Integer(ref max_steps) = self.heap.clone(h) {
-                    if max_steps.to_isize().map(|i| i >= -1).unwrap_or(false) {
-                        let n = self.store(self.deref(self[temp_v!(1)]));
-
-                        match n {
-                            Addr::Con(h) if self.heap.integer_at(h) => {
-                                if let HeapCellValue::Integer(ref n) = &self.heap[h] {
-                                    if n.as_ref() == &0 {
-                                        let xs0 = self[temp_v!(3)];
-                                        let xs  = self[temp_v!(4)];
-
-                                        self.unify(xs0, xs);
-                                    } else {
-                                        self.skip_max_list_result(max_steps.as_ref());
-                                    }
-                                } else {
-                                    unreachable!()
-                                }
+            Addr::HeapCell(_) | Addr::StackCell(..) | Addr::AttrVar(_) => {
+                let stub = MachineError::functor_stub(clause_name!("$skip_max_list"), 4);
+                return Err(self.error_form(MachineError::instantiation_error(), stub));
+            }
+            addr => {
+                let max_steps_n =
+                    match Number::try_from((max_steps, &self.heap)) {
+                        Ok(Number::Integer(n)) => n.to_isize(),
+                        Ok(Number::Fixnum(n))  => Some(n),
+                        _ => None,
+                    };
+
+                if max_steps_n.map(|i| i >= -1).unwrap_or(false) {
+                    let n = self.store(self.deref(self[temp_v!(1)]));
+
+                    match Number::try_from((n, &self.heap)) {
+                        Ok(Number::Integer(n)) => {
+                            if n.as_ref() == &0 {
+                                let xs0 = self[temp_v!(3)];
+                                let xs  = self[temp_v!(4)];
+
+                                self.unify(xs0, xs);
+                            } else {
+                                self.skip_max_list_result(max_steps_n);
                             }
-                            _ => {
-                                self.skip_max_list_result(max_steps.as_ref());
+                        }
+                        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);
                             }
                         }
-                    } else {
-                        self.fail = true;
+                        _ => {
+                            self.skip_max_list_result(max_steps_n);
+                        }
                     }
                 } else {
-                    unreachable!()
+                    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,
+                        )
+                    );
                 }
             }
-            Addr::HeapCell(_) | Addr::StackCell(..) => {
-                let stub = MachineError::functor_stub(clause_name!("$skip_max_list"), 4);
-                return Err(self.error_form(MachineError::instantiation_error(), stub));
-            }
-            addr => {
-                let stub = MachineError::functor_stub(clause_name!("$skip_max_list"), 4);
-                return Err(
-                    self.error_form(
-                        MachineError::type_error(
-                            self.heap.h(),
-                            ValidType::Integer,
-                            addr
-                        ),
-                        stub,
-                    )
-                );
-            }
-        };
+        }
 
         Ok(())
     }
@@ -671,6 +678,10 @@ impl MachineState {
                 let addr = self.heap.put_constant(Constant::Integer(n));
                 self.unify(nx, addr);
             }
+            Ok(Term::Constant(_, Constant::Fixnum(n))) => {
+                let addr = self.heap.put_constant(Constant::Fixnum(n));
+                self.unify(nx, addr);
+            }
             Ok(Term::Constant(_, Constant::CharCode(c))) => {
                 self.unify(nx, Addr::CharCode(c))
             }
@@ -774,17 +785,18 @@ impl MachineState {
             }
             &SystemClauseType::BindFromRegister => {
                 let reg = self.store(self.deref(self[temp_v!(2)]));
-                let n = match reg {
-                    Addr::Con(h) =>
-                        if let HeapCellValue::Integer(ref n) = &self.heap[h] {
+                let n =
+                    match Number::try_from((reg, &self.heap)) {
+                        Ok(Number::Integer(n)) => {
                             n.to_usize()
-                        } else {
+                        }
+                        Ok(Number::Fixnum(n)) => {
+                            usize::try_from(n).ok()
+                        }
+                        _ => {
                             unreachable!()
                         }
-                    _ => {
-                        unreachable!()
-                    }
-                };
+                    };
 
                 if let Some(n) = n {
                     if n <= MAX_ARITY {
@@ -1020,15 +1032,36 @@ impl MachineState {
                                 let mut chars = String::new();
 
                                 for addr in addrs {
-                                    match addr {
-                                        Addr::Con(h) if self.heap.integer_at(h) => {
-                                            if let HeapCellValue::Integer(ref n) = &self.heap[h] {
-                                                let c = self.int_to_char_code(&n, "atom_codes", 2)?;
-                                                chars.push(std::char::from_u32(c).unwrap());
-                                            } else {
-                                                unreachable!()
+                                    match Number::try_from((addr, &self.heap)) {
+                                        Ok(Number::Fixnum(n)) => {
+                                            match u32::try_from(n) {
+                                                Ok(c) => {
+                                                    chars.push(std::char::from_u32(c).unwrap());
+                                                }
+                                                _ => {
+                                                    let c = self.int_to_char_code(
+                                                        &Integer::from(n),
+                                                        "atom_codes",
+                                                        2,
+                                                    )?;
+
+                                                    chars.push(std::char::from_u32(c).unwrap());
+                                                }
                                             }
+
+                                            continue;
+                                        }
+                                        Ok(Number::Integer(n)) => {
+                                            let c = self.int_to_char_code(&n, "atom_codes", 2)?;
+                                            chars.push(std::char::from_u32(c).unwrap());
+
+                                            continue;
+                                        }
+                                        _ => {
                                         }
+                                    }
+
+                                    match addr {
                                         Addr::CharCode(c) => {
                                             chars.push(std::char::from_u32(c).unwrap());
                                         }
@@ -1056,7 +1089,9 @@ impl MachineState {
                             }
                         }
                     }
-                    _ => unreachable!(),
+                    _ => {
+                        unreachable!()
+                    }
                 };
             }
             &SystemClauseType::AtomLength => {
@@ -1088,17 +1123,6 @@ impl MachineState {
 
                 self.unify(a2, len);
             }
-            &SystemClauseType::CallAttributeGoals => {
-                let p = self.attr_var_init.project_attrs_loc;
-
-                if self.last_call {
-                    self.execute_at_index(2, dir_entry!(p));
-                } else {
-                    self.call_at_index(2, dir_entry!(p));
-                }
-
-                return Ok(());
-            }
             &SystemClauseType::CallContinuation => {
                 let stub = MachineError::functor_stub(clause_name!("call_continuation"), 1);
 
@@ -1201,21 +1225,23 @@ impl MachineState {
                 let n = self[temp_v!(1)];
                 let chs = self[temp_v!(2)];
 
-                let string = match self.store(self.deref(n)) {
-                    Addr::Float(OrderedFloat(n)) => {
-                        format!("{0:<20?}", n)
-                    }
-                    Addr::Con(h) if self.heap.integer_at(h) => {
-                        if let HeapCellValue::Integer(ref n) = &self.heap[h] {
+                let n = self.store(self.deref(n));
+
+                let string =
+                    match Number::try_from((n, &self.heap)) {
+                        Ok(Number::Float(OrderedFloat(n))) => {
+                            format!("{0:<20?}", n)
+                        }
+                        Ok(Number::Fixnum(n)) => {
                             n.to_string()
-                        } else {
+                        }
+                        Ok(Number::Integer(n)) => {
+                            n.to_string()
+                        }
+                        _ => {
                             unreachable!()
                         }
-                    }
-                    _ => {
-                        unreachable!()
-                    }
-                };
+                    };
 
                 let chars = string.trim().chars().map(|c| Addr::Char(c));
                 let char_list = Addr::HeapCell(self.heap.to_list(chars));
@@ -1226,21 +1252,21 @@ impl MachineState {
                 let n = self[temp_v!(1)];
                 let chs = self[temp_v!(2)];
 
-                let string = match self.store(self.deref(n)) {
-                    Addr::Float(OrderedFloat(n)) => {
-                        format!("{0:<20?}", n)
-                    }
-                    Addr::Con(h) if self.heap.integer_at(h) => {
-                        if let HeapCellValue::Integer(ref n) = &self.heap[h] {
+                let string =
+                    match Number::try_from((n, &self.heap)) {
+                        Ok(Number::Float(OrderedFloat(n))) => {
+                            format!("{0:<20?}", n)
+                        }
+                        Ok(Number::Fixnum(n)) => {
                             n.to_string()
-                        } else {
+                        }
+                        Ok(Number::Integer(n)) => {
+                            n.to_string()
+                        }
+                        _ => {
                             unreachable!()
                         }
-                    }
-                    _ => {
-                        unreachable!()
-                    }
-                };
+                    };
 
                 let codes = string
                     .trim()
@@ -1322,33 +1348,37 @@ impl MachineState {
                     }
                     addr if addr.is_ref() => {
                         let a2 = self[temp_v!(2)];
+                        let a2 = self.store(self.deref(a2));
 
-                        match self.store(self.deref(a2)) {
-                            Addr::CharCode(code) => {
-                                if let Some(c) = std::char::from_u32(code) {
-                                    self.unify(Addr::Char(c), addr);
-                                } else {
-                                    self.fail = true;
-                                }
+                        let c = match Number::try_from((a2, &self.heap)) {
+                            Ok(Number::Integer(n)) => {
+                                self.int_to_char_code(&n, "char_code", 2)?
                             }
-                            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;
+                            Ok(Number::Fixnum(n)) => {
+                                self.int_to_char_code(&Integer::from(n), "char_code", 2)?
+                            }
+                            _ => {
+                                match addr {
+                                    Addr::CharCode(c) => {
+                                        c
+                                    }
+                                    _ => {
+                                        self.fail = true;
+                                        return Ok(());
+                                    }
                                 }
                             }
-                            _ => self.fail = true,
                         };
+
+                        if let Some(c) = std::char::from_u32(c) {
+                            self.unify(Addr::Char(c), addr);
+                        } else {
+                            self.fail = true;
+                        }
+                    }
+                    _ => {
+                        unreachable!();
                     }
-                    _ => unreachable!(),
                 };
             }
             &SystemClauseType::CheckCutPoint => {
@@ -1967,16 +1997,20 @@ impl MachineState {
                 let specifier = self[temp_v!(2)];
                 let op = self[temp_v!(3)];
 
-                let priority = match self.store(self.deref(priority)) {
-                    Addr::Con(h) if self.heap.integer_at(h) =>
-                        if let HeapCellValue::Integer(ref n) = &self.heap[h] {
+                let priority = self.store(self.deref(priority));
+
+                let priority =
+                    match Number::try_from((priority, &self.heap)) {
+                        Ok(Number::Integer(n)) => {
                             n.to_usize().unwrap()
-                        } else {
-                            unreachable!()
-                        },
-                    _ =>
-                        unreachable!(),
-                };
+                        }
+                        Ok(Number::Fixnum(n)) => {
+                            usize::try_from(n).unwrap()
+                        }
+                        _ => {
+                            unreachable!();
+                        }
+                    };
 
                 let specifier = match self.store(self.deref(specifier)) {
                     Addr::Con(h) if self.heap.atom_at(h) =>
@@ -2041,10 +2075,6 @@ impl MachineState {
                 let attr_goals = self.attr_var_init.attribute_goals.clone();
                 self.fetch_attribute_goals(attr_goals);
             }
-            &SystemClauseType::FetchAttributeGoals => {
-                let attr_goals = mem::replace(&mut self.attr_var_init.attribute_goals, vec![]);
-                self.fetch_attribute_goals(attr_goals);
-            }
             &SystemClauseType::GetAttributedVariableList => {
                 let attr_var = self.store(self.deref(self[temp_v!(1)]));
                 let attr_var_list =
@@ -2080,35 +2110,36 @@ impl MachineState {
             }
             &SystemClauseType::GetAttrVarQueueBeyond => {
                 let addr = self[temp_v!(1)];
+                let addr = self.store(self.deref(addr));
 
-                match self.store(self.deref(addr)) {
-                    Addr::Usize(b) => {
-                        let iter = self.gather_attr_vars_created_since(b);
-
-                        let var_list_addr = Addr::HeapCell(self.heap.to_list(iter));
-                        let list_addr = self[temp_v!(2)];
+                let b =
+                    match addr {
+                        Addr::Usize(b) => {
+                            Some(b)
+                        }
+                        _ => {
+                            match Number::try_from((addr, &self.heap)) {
+                                Ok(Number::Integer(n)) => {
+                                    n.to_usize()
+                                }
+                                Ok(Number::Fixnum(n)) => {
+                                    usize::try_from(n).ok()
+                                }
+                                _ => {
+                                    self.fail = true;
+                                    return Ok(());
+                                }
+                            }
+                        }
+                    };
 
-                        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);
+                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)];
+                    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!()
-                        }
-                    }
-                    _ => {
-                        self.fail = true;
-                    }
+                    self.unify(var_list_addr, list_addr);
                 }
             }
             &SystemClauseType::GetContinuationChunk => {
@@ -2327,51 +2358,58 @@ impl MachineState {
                     CWILCallPolicy::new_in_place(call_policy);
                 }
 
-                match (a1, a2) {
-                    (Addr::Usize(bp), Addr::Con(h))
-                        | (Addr::CutPoint(bp), Addr::Con(h))
-                        if self.heap.integer_at(h) => {
-                            if let HeapCellValue::Integer(n) = self.heap.clone(h) {
-                                match call_policy.downcast_mut::<CWILCallPolicy>().ok() {
-                                    Some(call_policy) => {
-                                        let count = call_policy.add_limit(Integer::from(&*n), bp);
-                                        let count = self.heap.to_unifiable(
-                                            HeapCellValue::Integer(Rc::new(count.clone()))
-                                        );
+                let n =
+                    match Number::try_from((a2, &self.heap)) {
+                        Ok(Number::Integer(n)) => {
+                            Integer::from(&*n.clone())
+                        }
+                        Ok(Number::Fixnum(n)) => {
+                            Integer::from(n)
+                        }
+                        _ => {
+                            let stub = MachineError::functor_stub(
+                                clause_name!("call_with_inference_limit"),
+                                3,
+                            );
 
-                                        let a3 = self[temp_v!(3)];
+                            let type_error = self.error_form(
+                                MachineError::type_error(
+                                    self.heap.h(),
+                                    ValidType::Integer,
+                                    a2,
+                                ),
+                                stub,
+                            );
 
-                                        self.unify(a3, count);
-                                    }
-                                    None => {
-                                        panic!(
-                                            "install_inference_counter: should have installed \\
-                                             CWILCallPolicy."
-                                        )
-                                    }
-                                }
-                            } else {
-                                unreachable!()
-                            }
+                            self.throw_exception(type_error);
+                            return Ok(());
                         }
-                    _ => {
-                        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,
-                        );
+                match a1 {
+                    Addr::Usize(bp) | Addr::CutPoint(bp) => {
+                        match call_policy.downcast_mut::<CWILCallPolicy>().ok() {
+                            Some(call_policy) => {
+                                let count = call_policy.add_limit(n, bp).clone();
+                                let count = self.heap.to_unifiable(
+                                    HeapCellValue::Integer(Rc::new(count))
+                                );
 
-                        self.throw_exception(type_error)
+                                let a3 = self[temp_v!(3)];
+                                self.unify(a3, count);
+                            }
+                            None => {
+                                panic!(
+                                    "install_inference_counter: should have installed \\
+                                     CWILCallPolicy."
+                                )
+                            }
+                        }
                     }
-                };
+                    _ => {
+                        unreachable!();
+                    }
+                }
             }
             &SystemClauseType::ModuleExists => {
                 let module = self.store(self.deref(self[temp_v!(1)]));
@@ -2582,9 +2620,9 @@ impl MachineState {
 
                         match a1 {
                             Addr::Usize(bp) | Addr::CutPoint(bp) => {
-                                let count = call_policy.remove_limit(bp);
+                                let count = call_policy.remove_limit(bp).clone();
                                 let count = self.heap.to_unifiable(
-                                    HeapCellValue::Integer(Rc::new(count.clone())),
+                                    HeapCellValue::Integer(Rc::new(count)),
                                 );
 
                                 let a2 = self[temp_v!(2)];
@@ -3029,29 +3067,24 @@ impl MachineState {
                     Addr::CharCode(c) => {
                         Integer::from(c)
                     }
-                    Addr::Con(h) if self.heap.integer_at(h) => {
-                        if let HeapCellValue::Integer(ref n) = &self.heap[h] {
-                            Integer::from(&**n)
-                        } else {
-                            unreachable!()
-                        }
-                    }
-                    Addr::Con(h) if self.heap.rational_at(h) => {
-                        if let HeapCellValue::Rational(r) = &self.heap[h] {
-                            if r.denom() == &1 {
-                                r.numer().clone()
-                            } else {
+                    _ => {
+                        match Number::try_from((seed, &self.heap)) {
+                            Ok(Number::Fixnum(n)) => {
+                                Integer::from(n)
+                            }
+                            Ok(Number::Integer(n)) => {
+                                Integer::from(n.as_ref())
+                            }
+                            Ok(Number::Rational(n))
+                                if n.denom() == &1 => {
+                                    n.numer().clone()
+                                }
+                            _ => {
                                 self.fail = true;
                                 return Ok(());
                             }
-                        } else {
-                            unreachable!()
                         }
                     }
-                    _ => {
-                        self.fail = true;
-                        return Ok(());
-                    }
                 };
 
                 let mut rand = RANDOM_STATE.borrow_mut();
@@ -3195,43 +3228,33 @@ impl MachineState {
                     }
                 };
 
-                let arity = match self.store(self.deref(arity)) {
-                    Addr::Con(h) if self.heap.integer_at(h) => {
-                        if let HeapCellValue::Integer(ref n) = &self.heap[h] {
-                            n.clone()
-                        } else {
+                let arity = self.store(self.deref(arity));
+
+                let arity =
+                    match Number::try_from((arity, &self.heap)) {
+                        Ok(Number::Fixnum(n)) => {
+                            Integer::from(n)
+                        }
+                        Ok(Number::Integer(n)) => {
+                            Integer::from(n.as_ref())
+                        }
+                        _ => {
                             unreachable!()
                         }
-                    }
-                    _ => {
-                        unreachable!()
-                    }
-                };
+                    };
 
                 let first_idx = match indices
                     .code_dir
                     .get(&(name.clone(), arity.to_usize().unwrap()))
                 {
-                    Some(ref idx) => {
+                    Some(ref idx) if idx.local().is_some() => {
                         if let Some(idx) = idx.local() {
                             idx
                         } else {
-                            let arity = arity.to_usize().unwrap();
-                            let stub = MachineError::functor_stub(name.clone(), arity);
-                            let h = self.heap.h();
-
-                            let err = MachineError::existence_error(
-                                h,
-                                ExistenceError::Procedure(name, arity),
-                            );
-
-                            let err = self.error_form(err, stub);
-
-                            self.throw_exception(err);
-                            return Ok(());
+                            unreachable!()
                         }
                     }
-                    None => {
+                    _ => {
                         let arity = arity.to_usize().unwrap();
                         let stub = MachineError::functor_stub(name.clone(), arity);
                         let h = self.heap.h();
@@ -3279,7 +3302,7 @@ impl MachineState {
                 let mut printer = HCPrinter::new(&self, &indices.op_dir, PrinterOutputter::new());
 
                 if let &Addr::Con(h) = &ignore_ops {
-                   if let HeapCellValue::Atom(ref name, _) = &self.heap[h] {
+                       if let HeapCellValue::Atom(ref name, _) = &self.heap[h] {
                         printer.ignore_ops = name.as_str() == "true";
                     } else {
                         unreachable!()
@@ -3287,7 +3310,7 @@ impl MachineState {
                 }
 
                 if let &Addr::Con(h) = &numbervars {
-                   if let HeapCellValue::Atom(ref name, _) = &self.heap[h] {
+                       if let HeapCellValue::Atom(ref name, _) = &self.heap[h] {
                         printer.numbervars = name.as_str() == "true";
                     } else {
                         unreachable!()
@@ -3295,23 +3318,32 @@ impl MachineState {
                 }
 
                 if let &Addr::Con(h) = &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";
                     } else {
                         unreachable!()
                     }
                 }
 
-                if let &Addr::Con(h) = &max_depth {
-                    if let HeapCellValue::Integer(ref n) = &self.heap[h] {
+                match Number::try_from((max_depth, &self.heap)) {
+                    Ok(Number::Fixnum(n)) => {
+                        if let Ok(n) = usize::try_from(n) {
+                            printer.max_depth = n;
+                        } else {
+                            self.fail = true;
+                            return Ok(());
+                        }
+                    }
+                    Ok(Number::Integer(n)) => {
                         if let Some(n) = n.to_usize() {
                             printer.max_depth = n;
                         } else {
                             self.fail = true;
                             return Ok(());
                         }
-                    } else {
-                        unreachable!()
+                    }
+                    _ => {
+                        unreachable!();
                     }
                 }
 
index 2af0c13f109b83d577f8410a85dca66cfdd5044b..41331114f738bc60b41e49c0b2c3ea8f8f6bc486 100644 (file)
@@ -362,7 +362,7 @@ impl MachineState {
         wam.code_repo.cached_query = code;
 
         self.cp = LocalCodePtr::TopLevel(0, 0);
-        
+
         self.at_end_of_expansion = false;
         self.flags.double_quotes = DoubleQuotes::Chars;
 
index 0d93a3940bcd32ecb9d402a99d557d02c69b3d9d..99990896ab7cf80a3472a2f00dccfa510130b0f6 100644 (file)
@@ -13,6 +13,7 @@ use indexmap::{IndexMap, IndexSet};
 use std::borrow::BorrowMut;
 use std::cell::Cell;
 use std::collections::VecDeque;
+use std::convert::TryFrom;
 use std::mem;
 use std::ops::DerefMut;
 use std::rc::Rc;
@@ -211,8 +212,8 @@ fn setup_op_decl(
     };
 
     let prec = match *terms.pop().unwrap() {
-        Term::Constant(_, Constant::Integer(bi)) => match bi.to_usize() {
-            Some(n) if n <= 1200 => n,
+        Term::Constant(_, Constant::Fixnum(bi)) => match usize::try_from(bi) {
+            Ok(n) if n <= 1200 => n,
             _ => return Err(ParserError::InconsistentEntry),
         },
         _ => return Err(ParserError::InconsistentEntry),
@@ -232,8 +233,13 @@ fn setup_predicate_indicator(term: &mut Term) -> Result<PredicateKey, ParserErro
 
             let arity = arity
                 .to_constant()
-                .and_then(|c| c.to_integer())
-                .and_then(|n| n.to_usize())
+                .and_then(|c| {
+                    match c {
+                        Constant::Integer(n) => n.to_usize(),
+                        Constant::Fixnum(n) => usize::try_from(n).ok(),
+                        _ => None
+                    }
+                })
                 .ok_or(ParserError::InvalidModuleExport)?;
 
             let name  = name
@@ -246,7 +252,7 @@ fn setup_predicate_indicator(term: &mut Term) -> Result<PredicateKey, ParserErro
             } else {
                 Ok((name, arity + 2))
             }
-        }        
+        }
         _ => Err(ParserError::InvalidModuleExport),
     }
 }
@@ -344,7 +350,7 @@ fn setup_use_module_decl(mut terms: Vec<Box<Term>>) -> Result<ModuleSource, Pars
 
 fn setup_double_quotes(mut terms: Vec<Box<Term>>) -> Result<DoubleQuotes, ParserError> {
     let dbl_quotes = *terms.pop().unwrap();
-    
+
     match terms[0].as_ref() {
         Term::Constant(_, Constant::Atom(ref name, _))
             if name.as_str() == "double_quotes" => {
@@ -629,26 +635,26 @@ fn setup_declaration<'a, 'b, 'c>(
 
     match term {
         Term::Clause(_, name, mut terms, _) =>
-           match (name.as_str(), terms.len()) {
-               ("dynamic", 1) => {
-                   let (name, arity) = setup_predicate_indicator(&mut *terms.pop().unwrap())?;
-                   Ok(Declaration::Dynamic(name, arity))
-               }
-               ("initialization", 1) => {
-                   let mut rel_worker = RelationWorker::new(flags, line_num, col_num);
-                   let query_terms = rel_worker.setup_query(indices, terms, false)?;
-                   let queue = rel_worker.parse_queue(indices)?;
-
-                   Ok(Declaration::ModuleInitialization(query_terms, queue))
-               }
-               ("module", 2) =>
-                   Ok(Declaration::Module(setup_module_decl(terms, indices.atom_tbl())?)),
-               ("op", 3) =>
-                   Ok(Declaration::Op(setup_op_decl(terms, indices.atom_tbl())?)),
-               ("non_counted_backtracking", 1) => {
-                   let (name, arity) = setup_predicate_indicator(&mut *terms.pop().unwrap())?;
-                   Ok(Declaration::NonCountedBacktracking(name, arity))
-               }
+               match (name.as_str(), terms.len()) {
+                       ("dynamic", 1) => {
+                           let (name, arity) = setup_predicate_indicator(&mut *terms.pop().unwrap())?;
+                           Ok(Declaration::Dynamic(name, arity))
+                       }
+                       ("initialization", 1) => {
+                           let mut rel_worker = RelationWorker::new(flags, line_num, col_num);
+                           let query_terms = rel_worker.setup_query(indices, terms, false)?;
+                           let queue = rel_worker.parse_queue(indices)?;
+
+                           Ok(Declaration::ModuleInitialization(query_terms, queue))
+                       }
+                       ("module", 2) =>
+                           Ok(Declaration::Module(setup_module_decl(terms, indices.atom_tbl())?)),
+                       ("op", 3) =>
+                           Ok(Declaration::Op(setup_op_decl(terms, indices.atom_tbl())?)),
+                       ("non_counted_backtracking", 1) => {
+                           let (name, arity) = setup_predicate_indicator(&mut *terms.pop().unwrap())?;
+                           Ok(Declaration::NonCountedBacktracking(name, arity))
+                       }
                 ("set_prolog_flag", 2) => {
                     Ok(Declaration::SetPrologFlag(setup_double_quotes(terms)?))
                 }
@@ -656,27 +662,31 @@ fn setup_declaration<'a, 'b, 'c>(
                     let mut term = *terms.pop().unwrap();
 
                     match setup_predicate_indicator(&mut term) {
-                        Ok((name, arity)) =>
-                            Ok(Declaration::MultiFile(MultiFileIndicator::LocalScoped(name, arity))),
-                        _ =>
+                        Ok((name, arity)) => {
+                            Ok(Declaration::MultiFile(MultiFileIndicator::LocalScoped(name, arity)))
+                        }
+                        _ => {
                             setup_scoped_predicate_indicator(&mut term)
                                 .map(|key| {
                                     Declaration::MultiFile(MultiFileIndicator::ModuleScoped(key))
                                 })
+                        }
                     }
                 }
-               ("use_module", 1) => {
-                   Ok(Declaration::UseModule(setup_use_module_decl(terms)?))
+                       ("use_module", 1) => {
+                           Ok(Declaration::UseModule(setup_use_module_decl(terms)?))
                 }
-               ("use_module", 2) => {
-                   let (name, exports) = setup_qualified_import(terms, indices.atom_tbl())?;
-                   Ok(Declaration::UseQualifiedModule(name, exports))
-               }
-               _ => {
-                   Err(ParserError::InconsistentEntry)
+                       ("use_module", 2) => {
+                           let (name, exports) = setup_qualified_import(terms, indices.atom_tbl())?;
+                           Ok(Declaration::UseQualifiedModule(name, exports))
+                       }
+                       _ => {
+                           Err(ParserError::InconsistentEntry)
                 }
-           },
-        _ => Err(ParserError::InconsistentEntry),
+               },
+        _ => {
+            Err(ParserError::InconsistentEntry)
+        }
     }
 }
 
@@ -1249,7 +1259,7 @@ impl<'a> TopLevelBatchWorker<'a> {
 
         while !self.term_stream.eof()? {
             let term = self.term_stream.read_term(&indices.op_dir)?;
-            
+
             // if is_consistent is false, preds is non-empty.
             let term = if !term.is_consistent(&preds) {
                 self.process_result(indices, &mut preds)?;
index 1ba6e07ae3e0417f203f7f1c02e112cf3318d760..82ba62301f3383878144959196d40f0e298512ba 100644 (file)
@@ -105,7 +105,7 @@ macro_rules! functor_term {
     );
     (constant($h:expr, $e:expr), $arity:expr, $aux_lens:expr, $addendum:ident) => (
         from_constant!($e, $h, $arity, $aux_lens, $addendum)
-    );    
+    );
     (constant($e:expr), $arity:expr, $aux_lens:expr, $addendum:ident) => (
         from_constant!($e, 0, $arity, $aux_lens, $addendum)
     );
@@ -138,6 +138,9 @@ macro_rules! from_constant {
             &Constant::CharCode(c) => {
                 HeapCellValue::Addr(Addr::CharCode(c))
             }
+            &Constant::Fixnum(n) => {
+                HeapCellValue::Addr(Addr::Fixnum(n))
+            }
             &Constant::Integer(ref n) => {
                 HeapCellValue::Integer(n.clone())
             }
@@ -152,7 +155,7 @@ macro_rules! from_constant {
                 let h = len + $arity + 1 + $addendum.h() + $over_h;
 
                 $addendum.put_constant(Constant::String(s.clone()));
-                
+
                 HeapCellValue::Addr(Addr::PStrLocation(h, 0))
             }
             &Constant::Usize(u) => {
index d4437fdd4ec9a32821cef9410997b1267b0928bf..4f037c9a7c8767b579dd1fdffb56b8919227fc80 100644 (file)
     ;
        Term = [Item] -> !,
        (  atom(Item) ->
-         (  Item == user ->
-            catch('$$compile_batch', E, '$print_exception_with_check'(E))
-         ;  consult(Item)
-         )
+             (  Item == user ->
+                catch('$$compile_batch', E, '$print_exception_with_check'(E))
+             ;  consult(Item)
+             )
        ;
-         catch(throw(error(type_error(atom, Item), repl/0)),
-               E,
-               '$print_exception_with_check'(E))
+          catch(throw(error(type_error(atom, Item), repl/0)),
+                    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) :-
 
 '$needs_bracketing'(Value, Op) :-
     catch((functor(Value, F, _),
-          current_op(EqPrec, EqSpec, Op),
-          current_op(FPrec, _, F)),
-         _,
-         false),
+              current_op(EqPrec, EqSpec, Op),
+              current_op(FPrec, _, F)),
+             _,
+             false),
     (  EqPrec < FPrec -> true
     ;  '$quoted_token'(F) -> true
     ;  EqPrec == FPrec,
     ).
 
 '$gather_goals'([], VarList, Goals) :-
-    '$get_attr_var_queue_beyond'(0, AttrVars),
     '$gather_query_vars'(VarList, QueryVars),
-    '$call_attribute_goals'(QueryVars, AttrVars),
-    '$fetch_attribute_goals'(Goals).
+    copy_term(QueryVars, QueryVars, Goals).
 '$gather_goals'([Var = Value | Pairs], VarList, Goals) :-
     (  (  nonvar(Value)
        ;  '$is_a_different_variable'(Pairs, Value)
 '$module_export'(Source, PI) :-
     (  nonvar(PI) ->
        (  PI = Name / Arity ->
-         (  var(Name) -> throw(error(instantiation_error, Source))
-         ;  integer(Arity) ->
-            (  \+ atom(Name) -> throw(error(type_error(atom, Name), Source))
-            ;  Arity < 0 -> throw(error(domain_error(not_less_than_zero, Arity), Source))
-            ;  true
-            )
-         ;  throw(error(type_error(integer, Arity), Source))
-         )
+             (  var(Name) -> throw(error(instantiation_error, Source))
+             ;  integer(Arity) ->
+                (  \+ atom(Name) -> throw(error(type_error(atom, Name), Source))
+                ;  Arity < 0 -> throw(error(domain_error(not_less_than_zero, Arity), Source))
+                ;  true
+                )
+             ;  throw(error(type_error(integer, Arity), Source))
+             )
        ;  PI = op(Prec, Spec, Name) ->
-         (  integer(Prec) ->
-            (  \+ atom(Name) ->
-               throw(error(type_error(atom, Name), Source))
-            ;  Prec < 0 ->
-               throw(error(domain_error(not_less_than_zero, Prec), Source))
-            ;  Prec > 1200 ->
-               throw(error(domain_error(operator_precision, Prec), Source))
-            ;  memberchk(Spec, [xfy, yfx, xfx, fx, fy, yf, xf])
-            ;  throw(error(domain_error(operator_specification, Spec), Source))
-            )
-         ;  throw(error(type_error(integer, Prec), Source))
-         )
+             (  integer(Prec) ->
+                (  \+ atom(Name) ->
+                       throw(error(type_error(atom, Name), Source))
+                ;  Prec < 0 ->
+                       throw(error(domain_error(not_less_than_zero, Prec), Source))
+                ;  Prec > 1200 ->
+                       throw(error(domain_error(operator_precision, Prec), Source))
+                ;  memberchk(Spec, [xfy, yfx, xfx, fx, fy, yf, xf])
+                ;  throw(error(domain_error(operator_specification, Spec), Source))
+                )
+             ;  throw(error(type_error(integer, Prec), Source))
+             )
        ;  throw(error(type_error(module_export, PI), Source))
        )
     ;  throw(error(instantiation_error, Source))
@@ -334,10 +333,10 @@ expand_goals(UnexpandedGoals, ExpandedGoals) :-
     ),
     (  Goals = (Goal0, Goals0) ->
        (  expand_goals(Goal0, Goal1) ->
-         expand_goals(Goals0, Goals1),
-         thread_goals(Goal1, ExpandedGoals, Goals1, (','))
+             expand_goals(Goals0, Goals1),
+             thread_goals(Goal1, ExpandedGoals, Goals1, (','))
        ;  expand_goals(Goals0, Goals1),
-         ExpandedGoals = (Goal0, Goals1)
+             ExpandedGoals = (Goal0, Goals1)
        )
     ;  Goals = (Goals0 -> Goals1) ->
        expand_goals(Goals0, ExpandedGoals0),
@@ -358,9 +357,9 @@ thread_goals(Goals0, Goals1, Hole, Functor) :-
     nonvar(Goals0),
     (  Goals0 = [G | Gs] ->
        (  Gs == [] ->
-         Goals1 =.. [Functor, G, Hole]
+             Goals1 =.. [Functor, G, Hole]
        ;  Goals1 =.. [Functor, G, Goals2],
-         thread_goals(Gs, Goals2, Hole, Functor)
+             thread_goals(Gs, Goals2, Hole, Functor)
        )
     ;  Goals1 =.. [Functor, Goals0, Hole]
     ).
@@ -369,9 +368,9 @@ thread_goals(Goals0, Goals1, Functor) :-
     nonvar(Goals0),
     (  Goals0 = [G | Gs] ->
        (  Gs = [] ->
-         Goals1 = G
+             Goals1 = G
        ;  Goals1 =.. [Functor, G, Goals2],
-         thread_goals(Gs, Goals2, Functor)
+             thread_goals(Gs, Goals2, Functor)
        )
     ;  Goals1 = Goals0
     ).
index a1d8bb976d10865899ba39dd9a6c3f66004b527b..c44d9232df38bb52e2f10da07d1c80ca041542da 100644 (file)
@@ -187,6 +187,7 @@ impl fmt::Display for Addr {
             &Addr::Char(c) => write!(f, "Addr::Char({})", c),
             &Addr::CharCode(c) => write!(f, "Addr::CharCode({})", c),
             &Addr::EmptyList => write!(f, "Addr::EmptyList"),
+            &Addr::Fixnum(n) => write!(f, "Addr::Fixnum({})", n),
             &Addr::Float(fl) => write!(f, "Addr::Float({})", fl),
             &Addr::CutPoint(cp) => write!(f, "Addr::CutPoint({})", cp),
             &Addr::Con(ref c) => write!(f, "Addr::Con({})", c),
@@ -305,13 +306,13 @@ impl fmt::Display for Line {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         match self {
             &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::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::Indexing(ref indexing_instr) => write!(f, "{}", indexing_instr), 
-            &Line::IndexedChoice(ref indexed_choice_instr) => write!(f, "{}", indexed_choice_instr), 
-            &Line::Query(ref query_instr) => write!(f, "{}", query_instr), 
+            &Line::Indexing(ref indexing_instr) => write!(f, "{}", indexing_instr),
+            &Line::IndexedChoice(ref indexed_choice_instr) => write!(f, "{}", indexed_choice_instr),
+            &Line::Query(ref query_instr) => write!(f, "{}", query_instr),
         }
     }
 }
@@ -319,6 +320,7 @@ impl fmt::Display for Line {
 impl fmt::Display for Number {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         match self {
+            &Number::Fixnum(n) => write!(f, "{}", n),
             &Number::Float(fl) => write!(f, "{}", fl),
             &Number::Integer(ref bi) => write!(f, "{}", bi),
             &Number::Rational(ref r) => write!(f, "{}", r),
index 3cafc8b705c059d4893f0398074bda008b57c744..a1cf2a4ef19efb468fbbd966a099ba3421225a69 100644 (file)
@@ -35,7 +35,7 @@ test_queries_on_call_with_inference_limit :-
             [true, 2],
             [inference_limit_exceeded, _]]),
     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)),
            [[1,true,!],
             [2,true,!],
index 762fca97df0f5c5680b4d2927edc7ffc0f7d3eee..98b787267439700273f1d5acae2c762d84afaa1d 100644 (file)
@@ -23,6 +23,6 @@ test_queries_on_facts :-
     retract(p(_,_,_)),
     assertz(p(Z, h(Z, W), f(W))),
     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).
index 600daaf67f8e65e4cfa9ebc8f70be27f203bf004..29e72cd83e75440a0613b2254a02610a9fd6256b 100644 (file)
@@ -62,4 +62,3 @@ cleanup :- abolish(p/3),
           abolish(h/1).
 
 :- initialization(test_queries_on_rules).
-