[[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)",
"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)",
"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"
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
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::*;
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};
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()))),
}
// 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))
}
}
}
// 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(),
}
}
+#[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)
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)) => {
}
(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)) => {
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))
}
}
}
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))),
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
}
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)?))
}
}
}
-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,
}
}
+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());
AtomCodes,
AtomLength,
BindFromRegister,
- CallAttributeGoals,
CallContinuation,
CharCode,
CharsToNumber,
EnqueueAttributedVar,
ExpandGoal,
ExpandTerm,
- FetchAttributeGoals,
FetchGlobalVar,
FetchGlobalVarWithOffset,
GetChar,
&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"),
&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")
("$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),
("$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),
}
},
&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) => {
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(),
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);
}
}
use std::cell::Cell;
use std::collections::VecDeque;
+use std::convert::TryFrom;
use std::path::PathBuf;
use std::rc::Rc;
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 {
}
}
+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),
}
}
+
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,
#[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,
#[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,
#[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())),
}
}
}
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;
#[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
}
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
}
&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));
}
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 {
}
}
+ 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, _) => {
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));
@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.
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).
use crate::prolog::rug::{Integer, Rational};
use std::cmp;
+use std::convert::TryFrom;
use std::f64;
use std::mem;
use std::rc::Rc;
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> {
}
&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())
n: Number,
) -> Result<Rc<Rational>, MachineError> {
match n {
+ Number::Fixnum(n) => {
+ Ok(Rc::new(Rational::from(n)))
+ }
Number::Rational(r) => {
Ok(r)
}
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))
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)?));
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))
}
"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) => {
}
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(
}
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);
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(
}
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);
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)) => {
}
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);
}
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)
}
}
+ #[inline]
pub(crate)
fn unary_float_fn_template<FloatFn>(&self, n1: Number, f: FloatFn) -> Result<f64, MachineStub>
where
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() {
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 {
}
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));
}
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(
}
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(
}
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(),
}
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(),
}
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(),
}
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(
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(),
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))
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))
}
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)
}
}
}
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 {
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) => {
}
}
}
-
+
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);
}
name,
arity,
);
-
+
self.machine_st = machine_st;
if let EvalSession::Error(err) = result {
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!(),
};
if addrs.is_empty() {
self.make_undefined(name.clone(), arity);
}
-
+
self.print_new_dynamic_clause(addrs, name.clone(), arity)
}
Err(err) => {
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!()
}
if addrs.is_empty() {
self.make_undefined(name.clone(), arity);
}
-
+
self.print_new_dynamic_clause(addrs, name.clone(), arity)
}
Err(err) => {
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;
Constant::EmptyList => {
Addr::EmptyList
}
+ Constant::Fixnum(n) => {
+ Addr::Fixnum(n)
+ }
Constant::Integer(n) => {
Addr::Con(self.push(HeapCellValue::Integer(n)))
}
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 {
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
}
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;
Con(usize),
CutPoint(usize),
EmptyList,
+ Fixnum(isize),
Float(OrderedFloat<f64>),
Lis(usize),
HeapCell(usize),
#[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
}
_ => {
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
- }
}
}
&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() {
} else {
return None;
}
-
+
match addr {
Addr::PStrLocation(h, n) => {
if let &HeapCellValue::PartialString(ref pstr, _) = &self.machine_st.heap[h] {
}
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));
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(_) => {
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)
use indexmap::{IndexMap, IndexSet};
use std::cmp::Ordering;
+use std::convert::TryFrom;
use std::rc::Rc;
macro_rules! try_or_fail {
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()));
) 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;
}
}
}
}
}
- (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;
}
}
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;
}
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()));
) 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;
}
}
}
}
}
- (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;
}
}
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;
}
}
HeapCellValue::Integer(ref n1) => {
match c {
+ Constant::Fixnum(n2) => {
+ n1.to_isize() != Some(*n2)
+ }
Constant::Integer(ref n2) => {
n1 != n2
}
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) => {
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) => {
&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) => {
&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) => {
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) => {
&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) => {
}
}
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(_) => {
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;
}
};
- 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(())
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)];
(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;
}
}
}
}
(
- &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;
}
}
}
}
}
- (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;
}
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) => {
&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]));
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) {
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) => {
}
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);
}
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),
}
}
(
- 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;
}
}
}
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 {});
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));
+ }
};
}
&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))
+ }
}
}
use indexmap::IndexMap;
use std::collections::VecDeque;
+use std::convert::TryFrom;
use std::fs::File;
use std::mem;
use std::ops::Index;
#[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
}
}
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();
lib_path.clone(),
)
);
-
+
compile_user_module(&mut wam,
Stream::from(LISTS),
true,
lib_path.clone(),
),
);
-
+
compile_user_module(&mut wam,
Stream::from(ISO_EXT),
true,
lib_path.clone(),
)
);
-
+
compile_user_module(&mut wam,
Stream::from(SI),
true,
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,
}
_ => 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 {
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));
}
};
- 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) {
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);
}
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 {
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};
}
}
- 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 {
};
}
- 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(())
}
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))
}
}
&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 {
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());
}
}
}
}
- _ => unreachable!(),
+ _ => {
+ unreachable!()
+ }
};
}
&SystemClauseType::AtomLength => {
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);
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));
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()
}
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 => {
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) =>
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 =
}
&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 => {
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)]));
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)];
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();
}
};
- 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();
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!()
}
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!()
}
if let &Addr::Con(h) = "ed {
- if let HeapCellValue::Atom(ref name, _) = &self.heap[h] {
+ if let HeapCellValue::Atom(ref name, _) = &self.heap[h] {
printer.quoted = name.as_str() == "true";
} else {
unreachable!()
}
}
- if let &Addr::Con(h) = &max_depth {
- if let HeapCellValue::Integer(ref n) = &self.heap[h] {
+ match Number::try_from((max_depth, &self.heap)) {
+ Ok(Number::Fixnum(n)) => {
+ if let Ok(n) = usize::try_from(n) {
+ printer.max_depth = n;
+ } else {
+ self.fail = true;
+ return Ok(());
+ }
+ }
+ Ok(Number::Integer(n)) => {
if let Some(n) = n.to_usize() {
printer.max_depth = n;
} else {
self.fail = true;
return Ok(());
}
- } else {
- unreachable!()
+ }
+ _ => {
+ unreachable!();
}
}
wam.code_repo.cached_query = code;
self.cp = LocalCodePtr::TopLevel(0, 0);
-
+
self.at_end_of_expansion = false;
self.flags.double_quotes = DoubleQuotes::Chars;
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;
};
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),
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
} else {
Ok((name, arity + 2))
}
- }
+ }
_ => Err(ParserError::InvalidModuleExport),
}
}
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" => {
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)?))
}
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)
+ }
}
}
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)?;
);
(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)
);
&Constant::CharCode(c) => {
HeapCellValue::Addr(Addr::CharCode(c))
}
+ &Constant::Fixnum(n) => {
+ HeapCellValue::Addr(Addr::Fixnum(n))
+ }
&Constant::Integer(ref n) => {
HeapCellValue::Integer(n.clone())
}
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) => {
;
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))
),
( 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),
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]
).
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
).
&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),
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),
}
}
}
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),
[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,!],
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).
abolish(h/1).
:- initialization(test_queries_on_rules).
-