[[package]]
name = "prolog_parser"
-version = "0.8.47"
-source = "registry+https://github.com/rust-lang/crates.io-index"
+version = "0.8.48"
dependencies = [
"lexical 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"num-rug-adapter 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"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.47 (registry+https://github.com/rust-lang/crates.io-index)",
+ "prolog_parser 0.8.48",
"ref_thread_local 0.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"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.47 (registry+https://github.com/rust-lang/crates.io-index)" = "2cf575fc8b91b2d9a9487f13655cffb6f697a5294b74de9b24b6a5fbe987e229"
"checksum quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)" = "6ce23b6b870e8f94f81fb0a363d65d86675884b34a09043c81e5562f11c1f8e1"
"checksum 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.47", default-features = false }
+prolog_parser = { version = "0.8.48", path = "../prolog_parser", default-features = false }
ref_thread_local = "0.0.0"
rug = { version = "1.4.0", optional = true }
rustyline = "6.0.0"
fn add(self, rhs: Number) -> Self::Output {
match (self, rhs) {
- (Number::Integer(n1), Number::Integer(n2)) => Ok(Number::Integer(n1 + n2)), // add_i
+ (Number::Integer(n1), Number::Integer(n2)) => {
+ Ok(Number::Integer(Rc::new(Integer::from(&*n1) + &*n2))) // add_i
+ }
(Number::Integer(n1), Number::Float(OrderedFloat(n2)))
- | (Number::Float(OrderedFloat(n2)), Number::Integer(n1)) => {
+ | (Number::Float(OrderedFloat(n2)), Number::Integer(n1)) => {
Ok(Number::Float(add_f(float_i_to_f(&n1)?, n2)?))
}
(Number::Integer(n1), Number::Rational(n2))
- | (Number::Rational(n2), Number::Integer(n1)) => {
- Ok(Number::Rational(Rational::from(n1) + n2))
+ | (Number::Rational(n2), Number::Integer(n1)) => {
+ Ok(Number::Rational(Rc::new(Rational::from(&*n1) + &*n2)))
}
(Number::Rational(n1), Number::Float(OrderedFloat(n2)))
- | (Number::Float(OrderedFloat(n2)), Number::Rational(n1)) => {
+ | (Number::Float(OrderedFloat(n2)), Number::Rational(n1)) => {
Ok(Number::Float(add_f(float_r_to_f(&n1)?, n2)?))
}
(Number::Float(OrderedFloat(f1)), Number::Float(OrderedFloat(f2))) => {
Ok(Number::Float(add_f(f1, f2)?))
}
- (Number::Rational(r1), Number::Rational(r2)) => Ok(Number::Rational(r1 + r2)),
+ (Number::Rational(r1), Number::Rational(r2)) => {
+ Ok(Number::Rational(Rc::new(Rational::from(&*r1) + &*r2)))
+ }
}
}
}
fn neg(self) -> Self::Output {
match self {
- Number::Integer(n) => Number::Integer(-n),
+ Number::Integer(n) => Number::Integer(Rc::new(-Integer::from(&*n))),
Number::Float(OrderedFloat(f)) => Number::Float(OrderedFloat(-f)),
- Number::Rational(r) => Number::Rational(-r),
+ Number::Rational(r) => Number::Rational(Rc::new(-Rational::from(&*r))),
}
}
}
fn mul(self, rhs: Number) -> Self::Output {
match (self, rhs) {
- (Number::Integer(n1), Number::Integer(n2)) => Ok(Number::Integer(n1 * n2)), // mul_i
+ (Number::Integer(n1), Number::Integer(n2)) => {
+ Ok(Number::Integer(Rc::new(Integer::from(&*n1) * &*n2))) // mul_i
+ }
(Number::Integer(n1), Number::Float(OrderedFloat(n2)))
| (Number::Float(OrderedFloat(n2)), Number::Integer(n1)) => {
Ok(Number::Float(mul_f(float_i_to_f(&n1)?, n2)?))
}
(Number::Integer(n1), Number::Rational(n2))
| (Number::Rational(n2), Number::Integer(n1)) => {
- Ok(Number::Rational(Rational::from(n1) * n2))
+ Ok(Number::Rational(Rc::new(Rational::from(&*n1) * &*n2)))
}
(Number::Rational(n1), Number::Float(OrderedFloat(n2)))
| (Number::Float(OrderedFloat(n2)), Number::Rational(n1)) => {
(Number::Float(OrderedFloat(f1)), Number::Float(OrderedFloat(f2))) => {
Ok(Number::Float(mul_f(f1, f2)?))
}
- (Number::Rational(r1), Number::Rational(r2)) => Ok(Number::Rational(r1 * r2)),
+ (Number::Rational(r1), Number::Rational(r2)) => {
+ Ok(Number::Rational(Rc::new(Rational::from(&*r1) * &*r2)))
+ }
}
}
}
}
// Computes n ^ power. Ignores the sign of power.
-pub fn binary_pow(mut n: Integer, power: Integer) -> Integer {
- let mut power = power.abs();
+pub fn binary_pow(mut n: Integer, power: &Integer) -> Integer {
+ let mut power = Integer::from(power.abs_ref());
if power == 0 {
return Integer::from(1);
#[derive(Clone, PartialEq, Eq)]
pub enum Number {
Float(OrderedFloat<f64>),
- Integer(Integer),
- Rational(Rational),
+ Integer(Rc<Integer>),
+ Rational(Rc<Rational>),
}
impl Default for Number {
}
}
-impl Number {
- pub fn to_constant(self) -> Constant {
+impl Into<HeapCellValue> for Number {
+ #[inline]
+ fn into(self) -> HeapCellValue {
match self {
- Number::Integer(n) => Constant::Integer(n),
- Number::Float(f) => Constant::Float(f),
- Number::Rational(r) => Constant::Rational(r),
+ 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 is_positive(&self) -> bool {
match self {
- &Number::Integer(ref n) => n > &0,
+ &Number::Integer(ref n) => &**n > &0,
&Number::Float(OrderedFloat(f)) => f.is_sign_positive(),
- &Number::Rational(ref r) => r > &0,
+ &Number::Rational(ref r) => &**r > &0,
}
}
#[inline]
pub fn is_negative(&self) -> bool {
match self {
- &Number::Integer(ref n) => n < &0,
+ &Number::Integer(ref n) => &**n < &0,
&Number::Float(OrderedFloat(f)) => f.is_sign_negative(),
- &Number::Rational(ref r) => r < &0,
+ &Number::Rational(ref r) => &**r < &0,
}
}
#[inline]
pub fn is_zero(&self) -> bool {
match self {
- &Number::Integer(ref n) => n == &0,
+ &Number::Integer(ref n) => &**n == &0,
&Number::Float(f) => f == OrderedFloat(0f64),
- &Number::Rational(ref r) => r == &0,
+ &Number::Rational(ref r) => &**r == &0,
}
}
#[inline]
pub fn abs(self) -> Self {
match self {
- Number::Integer(n) => Number::Integer(n.abs()),
+ Number::Integer(n) => Number::Integer(Rc::new(Integer::from(n.abs_ref()))),
Number::Float(f) => Number::Float(OrderedFloat(f.abs())),
- Number::Rational(r) => Number::Rational(r.abs()),
+ Number::Rational(r) => Number::Rational(Rc::new(Rational::from(r.abs_ref()))),
}
}
}
-use prolog_parser::ast::*;
-
use crate::prolog::machine::machine_indices::*;
use crate::prolog::machine::machine_state::*;
}
}
+ #[inline]
pub fn machine_st(&self) -> &MachineState {
&self.machine_st
}
fn follow_heap(&mut self, h: usize) -> Addr {
match &self.machine_st.heap[h] {
- HeapCellValue::NamedStr(arity, _, _) => {
- for idx in (1..arity + 1).rev() {
+ &HeapCellValue::NamedStr(arity, _, _) => {
+ for idx in (1 .. arity + 1).rev() {
self.state_stack.push(Addr::HeapCell(h + idx));
}
Addr::Str(h)
}
- HeapCellValue::Addr(ref a) => {
- self.follow(a.clone())
+ &HeapCellValue::Addr(a) => {
+ self.follow(a)
}
HeapCellValue::PartialString(_) => {
self.follow(Addr::PStrLocation(h, 0))
}
+ HeapCellValue::Atom(..) | HeapCellValue::DBRef(_)
+ | HeapCellValue::Integer(_) | HeapCellValue::Rational(_) => {
+ Addr::Con(h)
+ }
+ HeapCellValue::Stream(_) => {
+ Addr::Stream(h)
+ }
}
}
let da = self.machine_st.store(self.machine_st.deref(addr));
match da {
- Addr::Con(Constant::String(n, s)) => {
- if !self.machine_st.machine_flags().double_quotes.is_atom() {
- if s.len() > n {
- if let Some(c) = s[n ..].chars().next() {
- let o = c.len_utf8();
-
- self.state_stack.push(Addr::Con(Constant::String(n+o, s.clone())));
-
- if self.machine_st.machine_flags().double_quotes.is_codes() {
- self.state_stack.push(Addr::Con(Constant::CharCode(c as u32)));
- } else {
- self.state_stack.push(Addr::Con(Constant::Char(c)));
- }
- }
- } else {
- return Addr::Con(Constant::EmptyList);
- }
- }
-
- Addr::Con(Constant::String(n, s))
- }
- Addr::Con(_) | Addr::DBRef(_) | Addr::Stream(_) => {
- da
- }
Addr::Lis(a) => {
self.state_stack.push(Addr::HeapCell(a + 1));
self.state_stack.push(Addr::HeapCell(a));
}
Addr::PStrLocation(h, n) => {
if let HeapCellValue::PartialString(ref pstr) = &self.machine_st.heap[h] {
- let s = pstr.block_as_str();
-
- if let Some(c) = s[n ..].chars().next() {
- if pstr.len() > n + c.len_utf8() {
+ if let Some(c) = pstr.range_from(n ..).next() {
+ if !pstr.at_end(n + c.len_utf8()) {
self.state_stack.push(Addr::PStrLocation(h, n + c.len_utf8()));
} else {
self.state_stack.push(Addr::HeapCell(h + 1));
}
- self.state_stack.push(Addr::Con(Constant::Char(c)));
+ self.state_stack.push(Addr::Char(c));
} else {
unreachable!()
}
Addr::PStrLocation(h, n)
}
- Addr::AttrVar(_) | Addr::HeapCell(_) | Addr::StackCell(_, _) => {
- da
- }
Addr::Str(s) => {
self.follow_heap(s) // record terms of structure.
}
+ Addr::Con(h) => {
+ if let HeapCellValue::PartialString(_) = &self.machine_st.heap[h] {
+ self.state_stack.push(Addr::HeapCell(h + 1));
+ }
+
+ Addr::Con(h)
+ }
+ da => {
+ da
+ }
}
}
}
impl<'a> Iterator for HCPreOrderIterator<'a> {
- type Item = HeapCellValue;
+ type Item = Addr;
fn next(&mut self) -> Option<Self::Item> {
- self.state_stack.pop().map(|a| match self.follow(a) {
- Addr::HeapCell(h) => {
- HeapCellValue::Addr(self.machine_st.heap[h].as_addr(h))
- }
- Addr::Str(s) => {
- match &self.machine_st.heap[s] {
- val @ HeapCellValue::NamedStr(..) => {
- val.clone()
- }
- _ => {
- unreachable!()
- }
- }
- }
- Addr::StackCell(fr, sc) => {
- HeapCellValue::Addr(self.machine_st.stack.index_and_frame(fr)[sc].clone())
- }
- da => {
- HeapCellValue::Addr(da)
- }
- })
+ self.state_stack.pop().map(|a| self.follow(a))
}
}
pub trait MutStackHCIterator
-where
- Self: Iterator<Item = HeapCellValue>,
+where Self: Iterator<Item = Addr>
{
fn stack(&mut self) -> &mut Vec<Addr>;
}
-pub struct HCPostOrderIterator<HCIter> {
- base_iter: HCIter,
- parent_stack: Vec<(usize, HeapCellValue)>, // number of children, parent node.
+pub struct HCPostOrderIterator<'a> {
+ base_iter: HCPreOrderIterator<'a>,
+ parent_stack: Vec<(usize, Addr)>, // number of children, parent node.
}
-impl<HCIter> Deref for HCPostOrderIterator<HCIter> {
- type Target = HCIter;
+impl<'a> Deref for HCPostOrderIterator<'a> {
+ type Target = HCPreOrderIterator<'a>;
fn deref(&self) -> &Self::Target {
&self.base_iter
}
}
-impl<HCIter: Iterator<Item = HeapCellValue>> HCPostOrderIterator<HCIter> {
- pub fn new(base_iter: HCIter) -> Self {
+impl<'a> HCPostOrderIterator<'a> {
+ pub fn new(base_iter: HCPreOrderIterator<'a>) -> Self {
HCPostOrderIterator {
base_iter,
parent_stack: vec![],
}
}
-impl<HCIter: Iterator<Item = HeapCellValue>> Iterator for HCPostOrderIterator<HCIter> {
- type Item = HeapCellValue;
+impl<'a> Iterator for HCPostOrderIterator<'a> {
+ type Item = Addr;
fn next(&mut self) -> Option<Self::Item> {
loop {
}
if let Some(item) = self.base_iter.next() {
- match item {
- HeapCellValue::NamedStr(arity, name, fix) => self
- .parent_stack
- .push((arity, HeapCellValue::NamedStr(arity, name, fix))),
- HeapCellValue::Addr(Addr::Lis(a)) => self
- .parent_stack
- .push((2, HeapCellValue::Addr(Addr::Lis(a)))),
- child_node => {
- return Some(child_node);
+ match self.base_iter.machine_st.heap.index_addr(&item).as_ref() {
+ &HeapCellValue::NamedStr(arity, ..) => {
+ self.parent_stack.push((arity, item));
+ }
+ &HeapCellValue::Addr(Addr::Lis(a)) => {
+ self.parent_stack.push((2, Addr::Lis(a)));
+ }
+ &HeapCellValue::Addr(Addr::PStrLocation(h, n)) => {
+ if let HeapCellValue::PartialString(ref pstr) = &self.machine_st.heap[h] {
+ let c = pstr.range_from(n ..).next().unwrap();
+ self.parent_stack.push((2, Addr::PStrLocation(h, n + c.len_utf8())));
+ } else {
+ unreachable!()
+ }
+ }
+ _ => {
+ return Some(item);
}
}
} else {
}
}
-pub type HCProperPostOrderIterator<'a> = HCPostOrderIterator<HCPreOrderIterator<'a>>;
-
impl MachineState {
pub fn pre_order_iter<'a>(&'a self, a: Addr) -> HCPreOrderIterator<'a> {
HCPreOrderIterator::new(self, a)
}
- pub fn post_order_iter<'a>(&'a self, a: Addr) -> HCProperPostOrderIterator<'a> {
+ pub fn post_order_iter<'a>(&'a self, a: Addr) -> HCPostOrderIterator<'a> {
HCPostOrderIterator::new(HCPreOrderIterator::new(self, a))
}
- pub fn acyclic_pre_order_iter<'a>(
- &'a self,
- a: Addr,
- ) -> HCAcyclicIterator<HCPreOrderIterator<'a>> {
+ pub fn acyclic_pre_order_iter<'a>(&'a self, a: Addr,) -> HCAcyclicIterator<'a> {
HCAcyclicIterator::new(HCPreOrderIterator::new(self, a))
}
&'a self,
a1: Addr,
a2: Addr,
- ) -> HCZippedAcyclicIterator<HCPreOrderIterator<'a>> {
+ ) -> HCZippedAcyclicIterator<'a> {
HCZippedAcyclicIterator::new(
HCPreOrderIterator::new(self, a1),
HCPreOrderIterator::new(self, a2),
}
}
-pub struct HCAcyclicIterator<HCIter> {
- iter: HCIter,
+pub struct HCAcyclicIterator<'a> {
+ iter: HCPreOrderIterator<'a>,
seen: IndexSet<Addr>,
}
-impl<HCIter: MutStackHCIterator> HCAcyclicIterator<HCIter> {
- pub fn new(iter: HCIter) -> Self {
+impl<'a> HCAcyclicIterator<'a> {
+ pub fn new(iter: HCPreOrderIterator<'a>) -> Self {
HCAcyclicIterator {
iter,
seen: IndexSet::new(),
}
}
-impl<HCIter> Deref for HCAcyclicIterator<HCIter> {
- type Target = HCIter;
+impl<'a> Deref for HCAcyclicIterator<'a> {
+ type Target = HCPreOrderIterator<'a>;
fn deref(&self) -> &Self::Target {
&self.iter
}
}
-impl<HCIter> Iterator for HCAcyclicIterator<HCIter>
-where
- HCIter: Iterator<Item = HeapCellValue> + MutStackHCIterator,
+impl<'a> Iterator for HCAcyclicIterator<'a>
{
- type Item = HeapCellValue;
+ type Item = Addr;
fn next(&mut self) -> Option<Self::Item> {
while let Some(addr) = self.iter.stack().pop() {
}
}
-pub struct HCZippedAcyclicIterator<HCIter> {
- i1: HCIter,
- i2: HCIter,
+pub struct HCZippedAcyclicIterator<'a> {
+ i1: HCPreOrderIterator<'a>,
+ i2: HCPreOrderIterator<'a>,
seen: IndexSet<(Addr, Addr)>,
pub first_to_expire: Ordering,
}
-impl<HCIter: MutStackHCIterator> HCZippedAcyclicIterator<HCIter> {
- pub fn new(i1: HCIter, i2: HCIter) -> Self {
+impl<'a> HCZippedAcyclicIterator<'a> {
+ pub fn new(i1: HCPreOrderIterator<'a>, i2: HCPreOrderIterator<'a>) -> Self {
HCZippedAcyclicIterator {
i1,
i2,
}
}
-impl<HCIter> Iterator for HCZippedAcyclicIterator<HCIter>
-where
- HCIter: Iterator<Item = HeapCellValue> + MutStackHCIterator,
+impl<'a> Iterator for HCZippedAcyclicIterator<'a>
{
- type Item = (HeapCellValue, HeapCellValue);
+ type Item = (Addr, Addr);
fn next(&mut self) -> Option<Self::Item> {
while let (Some(a1), Some(a2)) = (self.i1.stack().pop(), self.i2.stack().pop()) {
self.first_to_expire = Ordering::Less;
None
}
- _ => None,
+ _ => {
+ None
+ }
}
}
}
use crate::prolog::clause_types::*;
use crate::prolog::forms::*;
use crate::prolog::heap_iter::*;
+use crate::prolog::machine::heap::*;
use crate::prolog::machine::machine_indices::*;
use crate::prolog::machine::machine_state::*;
use crate::prolog::ordered_float::OrderedFloat;
*/
fn leftmost_leaf_has_property<P>(&self, property_check: P) -> bool
where
- P: Fn(Constant) -> bool,
+ P: Fn(Addr, &Heap) -> bool,
{
let mut addr = match self.state_stack.last().cloned() {
Some(addr) => addr,
None => return false,
};
- let mut parent_spec = DirectedOp::Left(clause_name!("-"), SharedOpDesc::new(200, FY));
+ let mut parent_spec = DirectedOp::Left(
+ clause_name!("-"),
+ SharedOpDesc::new(200, FY),
+ );
loop {
match self.machine_st.store(self.machine_st.deref(addr)) {
parent_spec = DirectedOp::Right(name.clone(), spec.clone());
}
}
- _ => return false,
+ _ => {
+ return false;
+ }
},
- Addr::Con(Constant::Integer(n)) => return property_check(Constant::Integer(n)),
- Addr::Con(Constant::Float(n)) => return property_check(Constant::Float(n)),
- Addr::Con(Constant::Rational(n)) => return property_check(Constant::Rational(n)),
- _ => return false,
+ addr => {
+ return property_check(addr, &self.machine_st.heap);
+ }
}
}
}
fn immediate_leaf_has_property<P>(&self, property_check: P) -> bool
where
- P: Fn(Constant) -> bool,
+ P: Fn(Addr, &Heap) -> bool,
{
let addr = match self.state_stack.last().cloned() {
Some(addr) => addr,
None => return false,
};
- match self.machine_st.store(self.machine_st.deref(addr)) {
- Addr::Con(c) => property_check(c),
- _ => false,
- }
+ let addr = self.machine_st.store(self.machine_st.deref(addr));
+ property_check(addr, &self.machine_st.heap)
}
}
#[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(|c| match c {
- Constant::Integer(n) => n > 0,
- Constant::Float(f) => f > OrderedFloat(0f64),
- Constant::Rational(r) => r > 0,
- _ => false,
- })
+ 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
+ }
+ }
+ }
+ 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(Constant::Integer(ref n)) if n >= &0 => {
- Some(numbervar(Integer::from(offset + n)))
+ Addr::Con(h) => {
+ if let &HeapCellValue::Integer(ref n) = &self.heap[h] {
+ if &**n >= &0 {
+ Some(numbervar(Integer::from(offset + &**n)))
+ } else {
+ None
+ }
+ } else {
+ None
+ }
}
_ => {
None
fn check_for_seen(
&mut self,
iter: &mut HCPreOrderIterator,
- ) -> Option<HeapCellValue> {
+ ) -> Option<Addr> {
iter.stack().last().cloned().and_then(|addr| {
let addr = self.machine_st.store(self.machine_st.deref(addr));
}
None => {
let offset = match functor_location(&addr) {
- Some(offset) => offset,
+ Some(offset) => {
+ offset
+ }
None => {
return iter.next();
}
}
fn print_char(&mut self, is_quoted: bool, c: char)
- {
+ {
if non_quoted_token(once(c)) {
let c = char_to_string(false, c);
}
}
- fn print_constant(
+ fn print_string_as_str(
&mut self,
- iter: &mut HCPreOrderIterator,
- max_depth: usize,
- c: Constant,
- op: &Option<DirectedOp>,
+ mut h: usize,
+ mut offset: usize,
+ quoted: bool,
) {
- match c {
- Constant::Atom(atom, spec) => {
- if let Some(_) = fetch_atom_op_spec(atom.clone(), spec, self.op_dir) {
- let mut result = String::new();
-
- if let Some(ref op) = op {
- if self.outputter.ends_with(&format!(" {}", op.as_str())) {
- result.push(' ');
- }
-
- result.push('(');
- }
-
- result += &self.print_op_addendum(atom.as_str());
-
- if op.is_some() {
- result.push(')');
- }
+ self.push_char('"');
- push_space_if_amb!(self, &result, {
- self.append_str(&result);
- });
- } else {
- push_space_if_amb!(self, atom.as_str(), {
- self.print_atom(&atom);
- });
- }
- }
- Constant::CharCode(c) => {
- self.append_str(&format!("{}", c as u32));
- }
- Constant::Char(c) => {
- self.print_char(self.quoted, c);
- }
- Constant::CutPoint(b) => {
- self.append_str(&format!("{}", b));
- }
- Constant::EmptyList => {
- self.append_str("[]");
- }
- Constant::Integer(n) => {
- self.print_number(Number::Integer(n), op);
- }
- Constant::Float(n) => {
- self.print_number(Number::Float(n), op);
- }
- Constant::Rational(n) => {
- self.print_number(Number::Rational(n), op);
- }
- Constant::String(n, s) if self.print_strings_as_strs => {
- self.print_string_as_str(iter, n, s);
- }
- Constant::String(n, s) => {
- self.print_string(iter, max_depth, n, s);
- }
- Constant::Usize(i) => {
- self.append_str(&format!("u{}", i));
- }
+ while let HeapCellValue::PartialString(ref pstr) = &self.machine_st.heap[h] {
+ let atom = String::from_iter(pstr.range_from(offset ..).map(|c| {
+ char_to_string(quoted, c)
+ }));
+
+ self.append_str(&atom);
+
+ h += 2;
+ offset = 0;
}
- }
-
- fn print_string_as_str(
- &mut self,
- iter: &mut HCPreOrderIterator,
- offset: usize,
- s: Rc<String>,
- ) {
- let atom = String::from_iter(s[offset ..].chars().map(|c| {
- char_to_string(true, c)
- }));
self.push_char('"');
- self.append_str(&atom);
- self.push_char('"');
-
- // eliminate lingering elements on the iterator stack (the
- // head and tail) which are there to treat the string as a
- // list.
- iter.stack().pop();
- iter.stack().pop();
}
fn print_string(
&mut self,
- iter: &mut HCPreOrderIterator,
mut max_depth: usize,
- offset: usize,
- s: Rc<String>)
+ mut h: usize,
+ mut offset: usize,
+ )
{
if !self.machine_st.machine_flags().double_quotes.is_atom() {
if self.check_max_depth(&mut max_depth) {
self.state_stack.push(TokenOrRedirect::Atom(clause_name!("...")));
return;
}
+
+ while let HeapCellValue::PartialString(ref pstr) = &self.machine_st.heap[h] {
+ if pstr.at_end(offset) && !self.at_cdr("") {
+ if let HeapCellValue::Addr(Addr::EmptyList) = &self.machine_st.heap[h+1] {
+ self.append_str("[]");
+ break;
+ } else {
+ h += 2;
+ offset = 0;
+ }
+ } else if self.ignore_ops {
+ let iter: Box<dyn Iterator<Item=char>> =
+ if self.max_depth == 0 {
+ Box::new(pstr.range_from(offset ..))
+ } else {
+ Box::new(pstr.range_from(offset ..).take(max_depth))
+ };
- if s.len() <= offset && !self.at_cdr("") {
- self.append_str("[]");
- } else if self.ignore_ops {
- let mut char_count = 0;
- let mut byte_len = 0;
+ let mut char_count = 0;
+ let mut byte_len = 0;
- let iter: Box<dyn Iterator<Item=char>> =
- if self.max_depth == 0 {
- Box::new(s[offset ..].chars())
- } else {
- Box::new(s[offset ..].chars().take(max_depth))
- };
+ for c in iter {
+ self.print_char(self.quoted, '.');
+ self.push_char('(');
- for c in iter {
- self.print_char(self.quoted, '.');
- self.push_char('(');
+ self.print_char(self.quoted, c);
+ self.push_char(',');
- self.print_char(self.quoted, c);
- self.push_char(',');
+ char_count += 1;
+ byte_len += c.len_utf8();
+ }
- char_count += 1;
- byte_len += c.len_utf8();
- }
+ let mut at_end = false;
+
+ if self.max_depth > 0 && !pstr.at_end(offset + byte_len) {
+ self.append_str("...");
+ at_end = true;
+ } else {
+ if let HeapCellValue::Addr(Addr::EmptyList) = &self.machine_st.heap[h+1] {
+ self.append_str("[]");
+ at_end = true;
+ }
+ }
- if self.max_depth > 0 && byte_len < s[offset ..].len() {
- self.append_str("...");
- } else {
- self.append_str("[]");
- }
+ for _ in 0 .. char_count {
+ self.push_char(')');
+ }
- for _ in 0 .. char_count {
- self.push_char(')');
- }
- } else {
- self.push_char('[');
+ if at_end {
+ break;
+ }
- let iter: Box<dyn Iterator<Item=char>> =
- if self.max_depth == 0 {
- Box::new(s[offset ..].chars())
- } else {
- Box::new(s[offset ..].chars().take(max_depth))
- };
+ max_depth -= char_count;
+ } else {
+ self.push_char('[');
- let mut byte_len = 0;
+ let iter: Box<dyn Iterator<Item=char>> =
+ if self.max_depth == 0 {
+ Box::new(pstr.range_from(offset ..))
+ } else {
+ Box::new(pstr.range_from(offset ..).take(max_depth))
+ };
- for c in iter {
- self.print_char(false, c);
- self.push_char(',');
+ let mut byte_len = 0;
+ let mut char_count = 0;
- byte_len += c.len_utf8();
- }
+ for c in iter {
+ self.print_char(false, c);
+ self.push_char(',');
+
+ byte_len += c.len_utf8();
+ char_count += 1;
+ }
- if self.max_depth > 0 && byte_len < s[offset ..].len() {
- self.append_str("...|...]");
- } else {
- self.outputter.truncate(self.outputter.len() - ','.len_utf8());
- self.push_char(']');
+ if self.max_depth > 0 && !pstr.at_end(offset + byte_len) {
+ self.append_str("...|...]");
+ break;
+ } else {
+ self.outputter.truncate(self.outputter.len() - ','.len_utf8());
+ self.push_char(']');
+ }
+
+ max_depth -= char_count;
}
- }
- iter.stack().pop();
- iter.stack().pop();
+ h += 2;
+ offset = 0;
+ }
} else {
- let atom = String::from_iter(s[offset ..].chars().map(|c| {
- char_to_string(self.quoted, c)
- }));
-
- self.push_char('"');
- self.append_str(&atom);
- self.push_char('"');
+ self.print_string_as_str(h, 0, self.quoted);
}
}
max_depth: usize,
) {
let add_brackets = if !self.ignore_ops {
- negated_operand
- || if let Some(ref op) = op {
- if self.numbervars && arity == 1 && name.as_str() == "$VAR" {
- !iter.immediate_leaf_has_property(|c| match c {
- Constant::Integer(n) => n >= 0,
- Constant::Float(f) => f >= OrderedFloat(0f64),
- Constant::Rational(r) => r >= 0,
- _ => false,
- }) && needs_bracketing(&spec, op)
- } else {
- needs_bracketing(&spec, op)
- }
+ negated_operand || if let Some(ref op) = op {
+ if self.numbervars && arity == 1 && name.as_str() == "$VAR" {
+ !iter.immediate_leaf_has_property(|addr, heap| {
+ match heap.index_addr(&addr).as_ref() {
+ &HeapCellValue::Integer(ref n) => &**n >= &0,
+ &HeapCellValue::Addr(Addr::Float(f)) => f >= OrderedFloat(0f64),
+ &HeapCellValue::Rational(ref r) => &**r >= &0,
+ _ => false
+ }
+ }) && needs_bracketing(&spec, op)
} else {
- is_functor_redirect && spec.prec() >= 1000
+ needs_bracketing(&spec, op)
}
+ } else {
+ is_functor_redirect && spec.prec() >= 1000
+ }
} else {
false
};
) {
let negated_operand = negated_op_needs_bracketing(iter, &op);
- let heap_val = match self.check_for_seen(iter) {
- Some(heap_val) => heap_val,
+ let addr = match self.check_for_seen(iter) {
+ Some(addr) => addr,
None => return,
};
-
- match heap_val {
- HeapCellValue::NamedStr(arity, name, spec) => {
+
+ match self.machine_st.heap.index_addr(&addr).as_ref() {
+ &HeapCellValue::NamedStr(arity, ref name, ref spec) => {
let spec = fetch_op_spec(name.clone(), arity, spec.clone(), self.op_dir);
if let Some(spec) = spec {
self.handle_op_as_struct(
- name,
+ name.clone(),
arity,
iter,
&op,
is_functor_redirect,
- spec,
+ spec.clone(),
negated_operand,
max_depth,
);
} else {
push_space_if_amb!(self, name.as_str(), {
- let ct = ClauseType::from(name, arity, spec);
+ let ct = ClauseType::from(name.clone(), arity, spec);
self.format_clause(iter, max_depth, arity, ct);
});
}
}
- HeapCellValue::Addr(Addr::Con(Constant::EmptyList)) => {
+ &HeapCellValue::Atom(ref atom, ref spec) => {
+ if let Some(_) = fetch_atom_op_spec(atom.clone(), spec.clone(), self.op_dir) {
+ let mut result = String::new();
+
+ if let Some(ref op) = op {
+ if self.outputter.ends_with(&format!(" {}", op.as_str())) {
+ result.push(' ');
+ }
+
+ result.push('(');
+ }
+
+ result += &self.print_op_addendum(atom.as_str());
+
+ if op.is_some() {
+ result.push(')');
+ }
+
+ push_space_if_amb!(self, &result, {
+ self.append_str(&result);
+ });
+ } else {
+ push_space_if_amb!(self, atom.as_str(), {
+ self.print_atom(&atom);
+ });
+ }
+ }
+ &HeapCellValue::Addr(Addr::CharCode(c)) => {
+ self.append_str(&format!("{}", c as u32));
+ }
+ &HeapCellValue::Addr(Addr::Char(c)) => {
+ self.print_char(self.quoted, c);
+ }
+ &HeapCellValue::Addr(Addr::CutPoint(b)) => {
+ self.append_str(&format!("{}", b));
+ }
+ &HeapCellValue::Addr(Addr::EmptyList) => {
if !self.at_cdr("") {
self.append_str("[]");
}
}
- HeapCellValue::Addr(Addr::Con(c)) => {
- self.print_constant(iter, max_depth, c, &op);
+ &HeapCellValue::Addr(Addr::Float(n)) => {
+ self.print_number(Number::Float(n), &op);
+ }
+ &HeapCellValue::Addr(Addr::Usize(u)) => {
+ self.append_str(&format!("{}", u));
}
- HeapCellValue::Addr(Addr::Lis(_)) | HeapCellValue::Addr(Addr::PStrLocation(..)) => {
+ &HeapCellValue::Addr(Addr::PStrLocation(..))
+ if !self.machine_st.flags.double_quotes.is_atom() => {
+ if self.ignore_ops {
+ self.format_struct(iter, max_depth, 2, clause_name!("."));
+ } else {
+ self.push_list(iter, max_depth);
+ }
+ }
+ &HeapCellValue::Addr(Addr::PStrLocation(h, n)) => {
+ if let HeapCellValue::PartialString(_) = &self.machine_st.heap[h] {
+ self.print_string(max_depth, h, n);
+
+ iter.stack().pop();
+ iter.stack().pop();
+ } else {
+ unreachable!()
+ }
+ }
+ &HeapCellValue::Addr(Addr::Lis(_)) => {
if self.ignore_ops {
self.format_struct(iter, max_depth, 2, clause_name!("."));
} else {
self.push_list(iter, max_depth);
}
}
- HeapCellValue::Addr(Addr::Stream(stream)) => {
+ &HeapCellValue::Addr(addr) => {
+ if let Some(offset_str) = self.offset_as_string(iter, addr) {
+ push_space_if_amb!(self, &offset_str, {
+ self.append_str(offset_str.as_str());
+ })
+ }
+ }
+ &HeapCellValue::Integer(ref n) => {
+ self.print_number(Number::Integer(n.clone()), &op);
+ }
+ &HeapCellValue::Rational(ref n) => {
+ self.print_number(Number::Rational(n.clone()), &op);
+ }
+ &HeapCellValue::PartialString(_)
+ if self.print_strings_as_strs => {
+ if let Addr::Con(h) = addr {
+ self.print_string_as_str(h, 0, true);
+ } else {
+ unreachable!()
+ }
+ }
+ &HeapCellValue::PartialString(_) => {
+ if let Addr::Con(h) = addr {
+ self.print_string(max_depth, h, 0);
+ } else {
+ unreachable!()
+ }
+ }
+ &HeapCellValue::Stream(ref stream) => {
if let Some(alias) = &stream.options.alias {
self.print_atom(alias);
} else {
}
}
}
- HeapCellValue::Addr(addr) => {
- if let Some(offset_str) = self.offset_as_string(iter, addr) {
- push_space_if_amb!(self, &offset_str, {
- self.append_str(offset_str.as_str());
- })
- }
- }
_ => {
- // This is the partial string case. We never clone a partial string
- // for printing purposes, so.. this.
- unreachable!()
}
}
}
let is_initial_index = self.lists.is_empty();
self.lists.push(Self::add_index(is_initial_index, index));
}
- &Term::Constant(_, Constant::String(n, ref s)) => {
+ &Term::Constant(_, Constant::String(ref s)) => {
let is_initial_index = self.lists.is_empty();
self.lists.push(Self::add_index(is_initial_index, index));
- let constant = Constant::String(n, s.clone());
+ let constant = Constant::String(s.clone());
let code = self.constants.entry(constant).or_insert(Vec::new());
let is_initial_index = code.is_empty();
}
&Term::Constant(_, ref constant) => {
if let Constant::Atom(ref name, _) = constant {
- if !name.as_str().is_empty() && name.as_str().chars().skip(1).next().is_none() {
+ if name.is_char() {
let c = name.as_str().chars().next().unwrap();
- let code = self.constants.entry(Constant::Char(c)).or_insert(vec![]);
+ let code = self.constants
+ .entry(Constant::Char(c))
+ .or_insert(vec![]);
code.push(Self::add_index(code.is_empty(), index));
}
use crate::prolog::clause_types::*;
use crate::prolog::forms::*;
+use crate::prolog::machine::heap::*;
use crate::prolog::machine::machine_errors::MachineStub;
use crate::prolog::machine::machine_indices::*;
-
use crate::prolog::rug::Integer;
use indexmap::IndexMap;
use std::collections::VecDeque;
+use std::rc::Rc;
fn reg_type_into_functor(r: RegType) -> MachineStub {
match r {
- RegType::Temp(r) => functor!("x", 1, [heap_integer!(Integer::from(r))]),
- RegType::Perm(r) => functor!("y", 1, [heap_integer!(Integer::from(r))]),
+ RegType::Temp(r) => functor!("x", [integer(r)]),
+ RegType::Perm(r) => functor!("y", [integer(r)]),
}
}
impl Level {
fn into_functor(self) -> MachineStub {
match self {
- Level::Root => functor!("level", 1, [heap_atom!("root")]),
- Level::Shallow => functor!("level", 1, [heap_atom!("shallow")]),
- Level::Deep => functor!("level", 1, [heap_atom!("deep")]),
+ Level::Root => functor!("level", [atom("root")]),
+ Level::Shallow => functor!("level", [atom("shallow")]),
+ Level::Deep => functor!("level", [atom("deep")]),
}
}
}
impl ArithmeticTerm {
fn into_functor(&self) -> MachineStub {
match self {
- &ArithmeticTerm::Reg(r) => reg_type_into_functor(r),
+ &ArithmeticTerm::Reg(r) => {
+ reg_type_into_functor(r)
+ }
&ArithmeticTerm::Interm(i) => {
- functor!("intermediate", 1, [heap_integer!(Integer::from(i))])
+ functor!("intermediate", [integer(i)])
+ }
+ &ArithmeticTerm::Number(ref n) => {
+ vec![n.clone().into()]
}
- &ArithmeticTerm::Number(ref n) => vec![heap_con!(n.clone().to_constant())],
}
}
}
pub fn to_functor(&self) -> MachineStub {
match self {
&ChoiceInstruction::TryMeElse(offset) => {
- functor!("try_me_else", 1, [heap_integer!(Integer::from(offset))])
+ functor!("try_me_else", [integer(offset)])
}
&ChoiceInstruction::RetryMeElse(offset) => {
- functor!("retry_me_else", 1, [heap_integer!(Integer::from(offset))])
+ functor!("retry_me_else", [integer(offset)])
+ }
+ &ChoiceInstruction::TrustMe => {
+ functor!("trust_me")
+ }
+ &ChoiceInstruction::DefaultRetryMeElse(offset) => {
+ functor!("default_retry_me_else", [integer(offset)])
+ }
+ &ChoiceInstruction::DefaultTrustMe => {
+ functor!("default_trust_me")
}
- &ChoiceInstruction::TrustMe => vec![heap_atom!("trust_me")],
- &ChoiceInstruction::DefaultRetryMeElse(offset) => functor!(
- "default_retry_me_else",
- 1,
- [heap_integer!(Integer::from(offset))]
- ),
- &ChoiceInstruction::DefaultTrustMe => vec![heap_atom!("default_trust_me")],
}
}
}
pub fn to_functor(&self, h: usize) -> MachineStub {
match self {
&CutInstruction::Cut(r) => {
- let mut stub = functor!("cut", 1, [heap_str!(h + 2)]);
- stub.append(&mut reg_type_into_functor(r));
- stub
+ let rt_stub = reg_type_into_functor(r);
+ functor!("cut", [aux(h, 0)], [rt_stub])
}
&CutInstruction::GetLevel(r) => {
- let mut stub = functor!("get_level", 1, [heap_str!(h + 2)]);
- stub.append(&mut reg_type_into_functor(r));
- stub
+ let rt_stub = reg_type_into_functor(r);
+ functor!("get_level", [aux(h, 0)], [rt_stub])
}
&CutInstruction::GetLevelAndUnify(r) => {
- let mut stub = functor!("get_level_and_unify", 1, [heap_str!(h + 2)]);
- stub.append(&mut reg_type_into_functor(r));
- stub
+ let rt_stub = reg_type_into_functor(r);
+ functor!("get_level_and_unify", [aux(h, 0)], [rt_stub])
+ }
+ &CutInstruction::NeckCut => {
+ functor!("neck_cut")
}
- &CutInstruction::NeckCut => vec![heap_atom!("neck_cut")],
}
}
}
pub fn to_functor(&self) -> MachineStub {
match self {
&IndexedChoiceInstruction::Try(offset) => {
- functor!("try", 1, [heap_integer!(Integer::from(offset))])
+ functor!("try", [integer(offset)])
}
&IndexedChoiceInstruction::Trust(offset) => {
- functor!("trust", 1, [heap_integer!(Integer::from(offset))])
+ functor!("trust", [integer(offset)])
}
&IndexedChoiceInstruction::Retry(offset) => {
- functor!("retry", 1, [heap_integer!(Integer::from(offset))])
+ functor!("retry", [integer(offset)])
}
}
}
t: usize,
) -> MachineStub {
let at_stub = at.into_functor();
-
- let mut stub = functor!(
+
+ functor!(
name,
- 2,
- [heap_cell!(h + 4), heap_integer!(Integer::from(t))]
- );
-
- stub.extend(at_stub.into_iter());
- stub
+ [aux(h, 0), integer(t)],
+ [at_stub]
+ )
}
fn arith_instr_bin_functor(
let at_1_stub = at_1.into_functor();
let at_2_stub = at_2.into_functor();
- let mut stub = functor!(
- name,
- 3,
- [
- heap_cell!(h + 4),
- heap_cell!(h + 4 + at_1_stub.len()),
- heap_integer!(Integer::from(t))
- ]
- );
-
- stub.extend(at_1_stub.into_iter());
- stub.extend(at_2_stub.into_iter());
-
- stub
+ functor!(
+ name,
+ [aux(h, 0), aux(h, 1), integer(t)],
+ [at_1_stub, at_2_stub]
+ )
}
impl ArithmeticInstruction {
&ArithmeticInstruction::Gcd(ref at_1, ref at_2, t) => {
arith_instr_bin_functor(h, "gcd", at_1, at_2, t)
}
- &ArithmeticInstruction::Sign(ref at, t) => arith_instr_unary_functor(h, "sign", at, t),
- &ArithmeticInstruction::Cos(ref at, t) => arith_instr_unary_functor(h, "cos", at, t),
- &ArithmeticInstruction::Sin(ref at, t) => arith_instr_unary_functor(h, "sin", at, t),
- &ArithmeticInstruction::Tan(ref at, t) => arith_instr_unary_functor(h, "tan", at, t),
- &ArithmeticInstruction::Log(ref at, t) => arith_instr_unary_functor(h, "log", at, t),
- &ArithmeticInstruction::Exp(ref at, t) => arith_instr_unary_functor(h, "exp", at, t),
- &ArithmeticInstruction::ACos(ref at, t) => arith_instr_unary_functor(h, "acos", at, t),
- &ArithmeticInstruction::ASin(ref at, t) => arith_instr_unary_functor(h, "asin", at, t),
- &ArithmeticInstruction::ATan(ref at, t) => arith_instr_unary_functor(h, "atan", at, t),
- &ArithmeticInstruction::Sqrt(ref at, t) => arith_instr_unary_functor(h, "sqrt", at, t),
- &ArithmeticInstruction::Abs(ref at, t) => arith_instr_unary_functor(h, "abs", at, t),
+ &ArithmeticInstruction::Sign(ref at, t) => {
+ arith_instr_unary_functor(h, "sign", at, t)
+ }
+ &ArithmeticInstruction::Cos(ref at, t) => {
+ arith_instr_unary_functor(h, "cos", at, t)
+ }
+ &ArithmeticInstruction::Sin(ref at, t) => {
+ arith_instr_unary_functor(h, "sin", at, t)
+ }
+ &ArithmeticInstruction::Tan(ref at, t) => {
+ arith_instr_unary_functor(h, "tan", at, t)
+ }
+ &ArithmeticInstruction::Log(ref at, t) => {
+ arith_instr_unary_functor(h, "log", at, t)
+ }
+ &ArithmeticInstruction::Exp(ref at, t) => {
+ arith_instr_unary_functor(h, "exp", at, t)
+ }
+ &ArithmeticInstruction::ACos(ref at, t) => {
+ arith_instr_unary_functor(h, "acos", at, t)
+ }
+ &ArithmeticInstruction::ASin(ref at, t) => {
+ arith_instr_unary_functor(h, "asin", at, t)
+ }
+ &ArithmeticInstruction::ATan(ref at, t) => {
+ arith_instr_unary_functor(h, "atan", at, t)
+ }
+ &ArithmeticInstruction::Sqrt(ref at, t) => {
+ arith_instr_unary_functor(h, "sqrt", at, t)
+ }
+ &ArithmeticInstruction::Abs(ref at, t) => {
+ arith_instr_unary_functor(h, "abs", at, t)
+ }
&ArithmeticInstruction::Float(ref at, t) => {
arith_instr_unary_functor(h, "float", at, t)
}
&ArithmeticInstruction::Floor(ref at, t) => {
arith_instr_unary_functor(h, "floor", at, t)
}
- &ArithmeticInstruction::Neg(ref at, t) => arith_instr_unary_functor(h, "-", at, t),
- &ArithmeticInstruction::Plus(ref at, t) => arith_instr_unary_functor(h, "+", at, t),
+ &ArithmeticInstruction::Neg(ref at, t) => {
+ arith_instr_unary_functor(h, "-", at, t)
+ }
+ &ArithmeticInstruction::Plus(ref at, t) => {
+ arith_instr_unary_functor(h, "+", at, t)
+ }
&ArithmeticInstruction::BitwiseComplement(ref at, t) => {
arith_instr_unary_functor(h, "\\", at, t)
}
pub fn to_functor(&self) -> MachineStub {
match self {
&ControlInstruction::Allocate(num_frames) => {
- functor!("allocate", 1, [heap_integer!(Integer::from(num_frames))])
- }
- &ControlInstruction::CallClause(ref ct, arity, _, false, _) => functor!(
- "call",
- 2,
- [
- heap_con!(Constant::Atom(ct.name(), None)),
- heap_integer!(Integer::from(arity))
- ]
- ),
- &ControlInstruction::CallClause(ref ct, arity, _, true, _) => functor!(
- "execute",
- 2,
- [
- heap_con!(Constant::Atom(ct.name(), None)),
- heap_integer!(Integer::from(arity))
- ]
- ),
- &ControlInstruction::Deallocate => vec![heap_atom!("deallocate")],
+ functor!("allocate", [integer(num_frames)])
+ }
+ &ControlInstruction::CallClause(ref ct, arity, _, false, _) => {
+ functor!("call", [clause_name(ct.name()), integer(arity)])
+ }
+ &ControlInstruction::CallClause(ref ct, arity, _, true, _) => {
+ functor!("execute", [clause_name(ct.name()), integer(arity)])
+ }
+ &ControlInstruction::Deallocate => {
+ functor!("deallocate")
+ }
&ControlInstruction::JmpBy(_, offset, ..) => {
- functor!("jmp_by", 1, [heap_integer!(Integer::from(offset))])
+ functor!("jmp_by", [integer(offset)])
+ }
+ &ControlInstruction::Proceed => {
+ functor!("proceed")
}
- &ControlInstruction::Proceed => vec![heap_atom!("proceed")],
}
}
}
impl IndexingInstruction {
pub fn to_functor(&self) -> MachineStub {
match self {
- &IndexingInstruction::SwitchOnTerm(vars, constants, lists, structures) => functor!(
- "switch_on_term",
- 4,
- [
- heap_integer!(Integer::from(vars)),
- heap_integer!(Integer::from(constants)),
- heap_integer!(Integer::from(lists)),
- heap_integer!(Integer::from(structures))
- ]
- ),
- &IndexingInstruction::SwitchOnConstant(constants, _) => functor!(
- "switch_on_constant",
- 1,
- [heap_integer!(Integer::from(constants))]
- ),
- &IndexingInstruction::SwitchOnStructure(structures, _) => functor!(
- "switch_on_structure",
- 1,
- [heap_integer!(Integer::from(structures))]
- ),
+ &IndexingInstruction::SwitchOnTerm(vars, constants, lists, structures) => {
+ functor!(
+ "switch_on_term",
+ [integer(vars),
+ integer(constants),
+ integer(lists),
+ integer(structures)]
+ )
+ }
+ &IndexingInstruction::SwitchOnConstant(constants, _) => {
+ functor!(
+ "switch_on_constant",
+ [integer(constants)]
+ )
+ }
+ &IndexingInstruction::SwitchOnStructure(structures, _) => {
+ functor!(
+ "switch_on_structure",
+ [integer(structures)]
+ )
+ }
}
}
}
impl FactInstruction {
pub fn to_functor(&self, h: usize) -> MachineStub {
match self {
- &FactInstruction::GetConstant(lvl, ref constant, r) => {
- let mut stub = functor!(
+ &FactInstruction::GetConstant(lvl, ref c, r) => {
+ let lvl_stub = lvl.into_functor();
+ let rt_stub = reg_type_into_functor(r);
+
+ functor!(
"get_constant",
- 3,
- [
- heap_str!(h + 4),
- heap_con!(constant.clone()),
- heap_str!(h + 6)
- ]
- );
-
- stub.append(&mut lvl.into_functor());
- stub.append(&mut reg_type_into_functor(r));
-
- stub
+ [aux(h, 0), constant(c), aux(h, 1)],
+ [lvl_stub, rt_stub]
+ )
}
&FactInstruction::GetList(lvl, r) => {
- let mut stub = functor!("get_list", 2, [heap_str!(h + 3), heap_str!(h + 5)]);
- stub.append(&mut lvl.into_functor());
- stub.append(&mut reg_type_into_functor(r));
+ let lvl_stub = lvl.into_functor();
+ let rt_stub = reg_type_into_functor(r);
- stub
+ functor!(
+ "get_list",
+ [aux(h, 0), aux(h, 1)],
+ [lvl_stub, rt_stub]
+ )
}
&FactInstruction::GetStructure(ref ct, arity, r) => {
- let mut stub = functor!(
- "get_structure",
- 3,
- [
- heap_con!(Constant::Atom(ct.name(), None)),
- heap_integer!(Integer::from(arity)),
- heap_str!(h + 4)
- ]
- );
- stub.append(&mut reg_type_into_functor(r));
+ let rt_stub = reg_type_into_functor(r);
- stub
+ functor!(
+ "get_structure",
+ [clause_name(ct.name()), integer(arity), aux(h, 0)],
+ [rt_stub]
+ )
}
&FactInstruction::GetValue(r, arg) => {
- let mut stub = functor!(
- "get_value",
- 2,
- [heap_str!(h + 3), heap_integer!(Integer::from(arg))]
- );
- stub.append(&mut reg_type_into_functor(r));
+ let rt_stub = reg_type_into_functor(r);
- stub
+ functor!(
+ "get_value",
+ [aux(h, 0), integer(arg)],
+ [rt_stub]
+ )
}
&FactInstruction::GetVariable(r, arg) => {
- let mut stub = functor!(
- "get_variable",
- 2,
- [heap_str!(h + 3), heap_integer!(Integer::from(arg))]
- );
- stub.append(&mut reg_type_into_functor(r));
+ let rt_stub = reg_type_into_functor(r);
- stub
+ functor!(
+ "get_variable",
+ [aux(h, 0), integer(arg)],
+ [rt_stub]
+ )
}
- &FactInstruction::UnifyConstant(ref constant) => {
- functor!("unify_constant", 1, [heap_con!(constant.clone())])
+ &FactInstruction::UnifyConstant(ref c) => {
+ functor!("unify_constant", [constant(c)], [])
}
&FactInstruction::UnifyLocalValue(r) => {
- let mut stub = functor!("unify_local_value", 1, [heap_str!(h + 2)]);
- stub.append(&mut reg_type_into_functor(r));
-
- stub
+ let rt_stub = reg_type_into_functor(r);
+
+ functor!(
+ "unify_local_value",
+ [aux(h, 0)],
+ [rt_stub]
+ )
}
&FactInstruction::UnifyVariable(r) => {
- let mut stub = functor!("unify_variable", 1, [heap_str!(h + 2)]);
- stub.append(&mut reg_type_into_functor(r));
+ let rt_stub = reg_type_into_functor(r);
- stub
+ functor!(
+ "unify_variable",
+ [aux(h, 0)],
+ [rt_stub]
+ )
}
&FactInstruction::UnifyValue(r) => {
- let mut stub = functor!("unify_value", 1, [heap_str!(h + 2)]);
- stub.append(&mut reg_type_into_functor(r));
-
- stub
+ let rt_stub = reg_type_into_functor(r);
+
+ functor!(
+ "unify_value",
+ [aux(h, 0)],
+ [rt_stub]
+ )
}
&FactInstruction::UnifyVoid(vars) => {
- functor!("unify_void", 1, [heap_integer!(Integer::from(vars))])
+ functor!("unify_void", [integer(vars)])
}
}
}
match self {
&QueryInstruction::PutUnsafeValue(norm, arg) => functor!(
"put_unsafe_value",
- 2,
- [
- heap_integer!(Integer::from(norm)),
- heap_integer!(Integer::from(arg))
- ]
+ [integer(norm), integer(arg)]
),
- &QueryInstruction::PutConstant(lvl, ref constant, r) => {
- let mut stub = functor!(
- "put_constant",
- 3,
- [
- heap_str!(h + 4),
- heap_con!(constant.clone()),
- heap_str!(h + 6)
- ]
- );
-
- stub.append(&mut lvl.into_functor());
- stub.append(&mut reg_type_into_functor(r));
+ &QueryInstruction::PutConstant(lvl, ref c, r) => {
+ let lvl_stub = lvl.into_functor();
+ let rt_stub = reg_type_into_functor(r);
- stub
+ functor!(
+ "put_constant",
+ [aux(h, 0), constant(c), aux(h, 1)],
+ [lvl_stub, rt_stub]
+ )
}
&QueryInstruction::PutList(lvl, r) => {
- let mut stub = functor!("put_list", 2, [heap_str!(h + 3), heap_str!(h + 5)]);
-
- stub.append(&mut lvl.into_functor());
- stub.append(&mut reg_type_into_functor(r));
-
- stub
+ let lvl_stub = lvl.into_functor();
+ let rt_stub = reg_type_into_functor(r);
+
+ functor!(
+ "put_list",
+ [aux(h, 0), aux(h, 1)],
+ [lvl_stub, rt_stub]
+ )
}
&QueryInstruction::PutStructure(ref ct, arity, r) => {
- let mut stub = functor!(
- "put_structure",
- 3,
- [
- heap_con!(Constant::Atom(ct.name(), None)),
- heap_integer!(Integer::from(arity)),
- heap_str!(h + 4)
- ]
- );
+ let rt_stub = reg_type_into_functor(r);
- stub.append(&mut reg_type_into_functor(r));
- stub
+ functor!(
+ "put_structure",
+ [clause_name(ct.name()), integer(arity), aux(h, 0)],
+ [rt_stub]
+ )
}
&QueryInstruction::PutValue(r, arg) => {
- let mut stub = functor!(
- "put_value",
- 2,
- [heap_str!(h + 3), heap_integer!(Integer::from(arg))]
- );
+ let rt_stub = reg_type_into_functor(r);
- stub.append(&mut reg_type_into_functor(r));
- stub
+ functor!(
+ "put_value",
+ [aux(h, 0), integer(arg)],
+ [rt_stub]
+ )
}
&QueryInstruction::GetVariable(r, arg) => {
- let mut stub = functor!(
- "get_variable",
- 2,
- [heap_str!(h + 3), heap_integer!(Integer::from(arg))]
- );
+ let rt_stub = reg_type_into_functor(r);
- stub.append(&mut reg_type_into_functor(r));
- stub
+ functor!(
+ "get_variable",
+ [aux(h, 0), integer(arg)],
+ [rt_stub]
+ )
}
&QueryInstruction::PutVariable(r, arg) => {
- let mut stub = functor!(
- "put_variable",
- 2,
- [heap_str!(h + 3), heap_integer!(Integer::from(arg))]
- );
+ let rt_stub = reg_type_into_functor(r);
- stub.append(&mut reg_type_into_functor(r));
- stub
+ functor!(
+ "put_variable",
+ [aux(h, 0), integer(arg)],
+ [rt_stub]
+ )
}
- &QueryInstruction::SetConstant(ref constant) => {
- functor!("set_constant", 1, [heap_con!(constant.clone())])
+ &QueryInstruction::SetConstant(ref c) => {
+ functor!("set_constant", [constant(c)], [])
}
&QueryInstruction::SetLocalValue(r) => {
- let mut stub = functor!("set_local_value", 1, [heap_str!(h + 2)]);
-
- stub.append(&mut reg_type_into_functor(r));
- stub
+ let rt_stub = reg_type_into_functor(r);
+
+ functor!(
+ "set_local_value",
+ [aux(h, 0)],
+ [rt_stub]
+ )
}
&QueryInstruction::SetVariable(r) => {
- let mut stub = functor!("set_variable", 1, [heap_str!(h + 2)]);
+ let rt_stub = reg_type_into_functor(r);
- stub.append(&mut reg_type_into_functor(r));
- stub
+ functor!(
+ "set_variable",
+ [aux(h, 0)],
+ [rt_stub]
+ )
}
&QueryInstruction::SetValue(r) => {
- let mut stub = functor!("set_value", 1, [heap_str!(h + 2)]);
+ let rt_stub = reg_type_into_functor(r);
- stub.append(&mut reg_type_into_functor(r));
- stub
+ functor!(
+ "set_value",
+ [aux(h, 0)],
+ [rt_stub]
+ )
}
&QueryInstruction::SetVoid(vars) => {
- functor!("set_void", 1, [heap_integer!(Integer::from(vars))])
+ functor!("set_void", [integer(vars)])
}
}
}
--- /dev/null
+use crate::prolog_parser::ast::*;
+
+use crate::prolog::arithmetic::*;
+use crate::prolog::clause_types::*;
+use crate::prolog::forms::*;
+use crate::prolog::machine::machine_errors::*;
+use crate::prolog::machine::machine_indices::*;
+use crate::prolog::machine::machine_state::*;
+use crate::prolog::ordered_float::*;
+use crate::prolog::rug::{Integer, Rational};
+
+use std::cmp;
+use std::f64;
+use std::mem;
+use std::rc::Rc;
+
+#[macro_export]
+macro_rules! try_numeric_result {
+ ($s: ident, $e: expr, $caller: expr) => (
+ match $e {
+ Ok(val) => {
+ Ok(val)
+ }
+ Err(e) => {
+ let caller_copy =
+ $caller.iter().map(|v| v.context_free_clone()).collect();
+
+ Err($s.error_form(MachineError::evaluation_error(e), caller_copy))
+ }
+ }
+ );
+}
+
+impl MachineState {
+ pub(crate)
+ fn get_number(&mut self, at: &ArithmeticTerm) -> Result<Number, MachineStub> {
+ match at {
+ &ArithmeticTerm::Reg(r) => {
+ self.arith_eval_by_metacall(r)
+ }
+ &ArithmeticTerm::Interm(i) => Ok(mem::replace(
+ &mut self.interms[i - 1],
+ Number::Integer(Rc::new(Integer::from(0))),
+ )),
+ &ArithmeticTerm::Number(ref n) => {
+ Ok(n.clone())
+ }
+ }
+ }
+
+ pub(super)
+ fn rational_from_number(
+ &self,
+ n: Number,
+ ) -> Result<Rc<Rational>, MachineError> {
+ match n {
+ Number::Rational(r) => {
+ Ok(r)
+ }
+ Number::Float(OrderedFloat(f)) => {
+ match Rational::from_f64(f) {
+ Some(r) => {
+ Ok(Rc::new(r))
+ }
+ None => {
+ Err(MachineError::instantiation_error())
+ }
+ }
+ }
+ Number::Integer(n) => {
+ Ok(Rc::new(Rational::from(&*n)))
+ }
+ }
+ }
+
+ pub(crate)
+ fn get_rational(
+ &mut self,
+ at: &ArithmeticTerm,
+ caller: MachineStub,
+ ) -> Result<(Rc<Rational>, MachineStub), MachineStub> {
+ let n = self.get_number(at)?;
+
+ match self.rational_from_number(n) {
+ Ok(r) => Ok((r, caller)),
+ Err(e) => Err(self.error_form(e, caller))
+ }
+ }
+
+ pub(crate)
+ fn arith_eval_by_metacall(&self, r: RegType) -> Result<Number, MachineStub> {
+ let a = self[r].clone();
+
+ let caller = MachineError::functor_stub(clause_name!("(is)"), 2);
+ let mut interms: Vec<Number> = Vec::with_capacity(64);
+
+ for addr in self.post_order_iter(a) {
+ match self.heap.index_addr(&addr).as_ref() {
+ &HeapCellValue::NamedStr(2, ref name, _) => {
+ let a2 = interms.pop().unwrap();
+ let a1 = interms.pop().unwrap();
+
+ match name.as_str() {
+ "+" => interms.push(try_numeric_result!(self, a1 + a2, caller)?),
+ "-" => interms.push(try_numeric_result!(self, a1 - a2, caller)?),
+ "*" => interms.push(try_numeric_result!(self, a1 * a2, caller)?),
+ "/" => interms.push(self.div(a1, a2)?),
+ "**" => interms.push(self.pow(a1, a2, "(is)")?),
+ "^" => interms.push(self.int_pow(a1, a2)?),
+ "max" => interms.push(self.max(a1, a2)?),
+ "min" => interms.push(self.min(a1, a2)?),
+ "rdiv" => {
+ let r1 = self.rational_from_number(a1);
+ let r2 = r1.and_then(|r1| {
+ self.rational_from_number(a2).map(|r2| (r1, r2))
+ });
+
+ match r2 {
+ Ok((r1, r2)) => {
+ let result = Number::Rational(Rc::new(self.rdiv(r1, r2)?));
+ interms.push(result);
+ }
+ Err(e) => {
+ return Err(self.error_form(e, caller));
+ }
+ }
+ }
+ "//" => interms.push(Number::Integer(Rc::new(self.idiv(a1, a2)?))),
+ "div" => interms.push(Number::Integer(Rc::new(self.int_floor_div(a1, a2)?))),
+ ">>" => interms.push(Number::Integer(Rc::new(self.shr(a1, a2)?))),
+ "<<" => interms.push(Number::Integer(Rc::new(self.shl(a1, a2)?))),
+ "/\\" => interms.push(Number::Integer(Rc::new(self.and(a1, a2)?))),
+ "\\/" => interms.push(Number::Integer(Rc::new(self.or(a1, a2)?))),
+ "xor" => interms.push(Number::Integer(Rc::new(self.xor(a1, a2)?))),
+ "mod" => interms.push(Number::Integer(Rc::new(self.modulus(a1, a2)?))),
+ "rem" => interms.push(Number::Integer(Rc::new(self.remainder(a1, a2)?))),
+ "atan2" => interms.push(Number::Float(OrderedFloat(self.atan2(a1, a2)?))),
+ "gcd" => interms.push(Number::Integer(Rc::new(self.gcd(a1, a2)?))),
+ _ => {
+ return Err(self.error_form(MachineError::instantiation_error(), caller))
+ }
+ }
+ }
+ &HeapCellValue::NamedStr(1, ref name, _) => {
+ let a1 = interms.pop().unwrap();
+
+ match name.as_str() {
+ "-" => interms.push(-a1),
+ "+" => interms.push(a1),
+ "cos" => interms.push(Number::Float(OrderedFloat(self.cos(a1)?))),
+ "sin" => interms.push(Number::Float(OrderedFloat(self.sin(a1)?))),
+ "tan" => interms.push(Number::Float(OrderedFloat(self.tan(a1)?))),
+ "sqrt" => interms.push(Number::Float(OrderedFloat(self.sqrt(a1)?))),
+ "log" => interms.push(Number::Float(OrderedFloat(self.log(a1)?))),
+ "exp" => interms.push(Number::Float(OrderedFloat(self.exp(a1)?))),
+ "acos" => interms.push(Number::Float(OrderedFloat(self.acos(a1)?))),
+ "asin" => interms.push(Number::Float(OrderedFloat(self.asin(a1)?))),
+ "atan" => interms.push(Number::Float(OrderedFloat(self.atan(a1)?))),
+ "abs" => interms.push(a1.abs()),
+ "float" => interms.push(Number::Float(OrderedFloat(self.float(a1)?))),
+ "truncate" => interms.push(Number::Integer(Rc::new(self.truncate(a1)))),
+ "round" => interms.push(Number::Integer(Rc::new(self.round(a1)?))),
+ "ceiling" => interms.push(Number::Integer(Rc::new(self.ceiling(a1)))),
+ "floor" => interms.push(Number::Integer(Rc::new(self.floor(a1)))),
+ "\\" => interms.push(Number::Integer(Rc::new(self.bitwise_complement(a1)?))),
+ "sign" => interms.push(Number::Integer(Rc::new(self.sign(a1)))),
+ _ => {
+ return Err(self.error_form(MachineError::instantiation_error(), caller));
+ }
+ }
+ }
+ &HeapCellValue::Integer(ref n) => {
+ interms.push(Number::Integer(n.clone()))
+ }
+ &HeapCellValue::Addr(Addr::Float(n)) => {
+ interms.push(Number::Float(n))
+ }
+ &HeapCellValue::Rational(ref n) => {
+ interms.push(Number::Rational(n.clone()))
+ }
+ &HeapCellValue::Atom(ref name, _) if name.as_str() == "pi" => {
+ interms.push(Number::Float(OrderedFloat(f64::consts::PI)))
+ }
+ _ => {
+ return Err(self.error_form(
+ MachineError::instantiation_error(),
+ caller,
+ ));
+ }
+ }
+ }
+
+ Ok(interms.pop().unwrap())
+ }
+
+ pub(crate)
+ fn rdiv(&self, r1: Rc<Rational>, r2: Rc<Rational>) -> Result<Rational, MachineStub> {
+ if &*r2 == &0 {
+ let stub = MachineError::functor_stub(clause_name!("(rdiv)"), 2);
+ Err(self.error_form(MachineError::evaluation_error(EvalError::ZeroDivisor), stub))
+ } else {
+ Ok(Rational::from(&*r1 / &*r2))
+ }
+ }
+
+ pub(crate)
+ fn int_floor_div(&self, n1: Number, n2: Number) -> Result<Integer, MachineStub> {
+ match n1 / n2 {
+ Ok(result) => Ok(rnd_i(&result).to_owned()),
+ Err(e) => {
+ let stub = MachineError::functor_stub(clause_name!("(div)"), 2);
+ Err(self.error_form(
+ MachineError::evaluation_error(
+ e
+ ),
+ stub
+ ))
+ }
+ }
+ }
+
+ pub(crate)
+ fn idiv(&self, n1: Number, n2: Number) -> Result<Integer, MachineStub> {
+ match (n1, n2) {
+ (Number::Integer(n1), Number::Integer(n2)) => {
+ if &*n2 == &0 {
+ let stub = MachineError::functor_stub(clause_name!("(//)"), 2);
+
+ Err(self.error_form(
+ MachineError::evaluation_error(
+ EvalError::ZeroDivisor
+ ),
+ stub,
+ ))
+ } else {
+ Ok(<(Integer, Integer)>::from(n1.div_rem_ref(&*n2)).0)
+ }
+ }
+ (Number::Integer(_), n2) => {
+ let stub = MachineError::functor_stub(clause_name!("(//)"), 2);
+
+ Err(self.error_form(
+ MachineError::type_error(
+ self.heap.h(),
+ ValidType::Integer,
+ n2,
+ ),
+ stub,
+ ))
+ }
+ (n1, _) => {
+ let stub = MachineError::functor_stub(clause_name!("(//)"), 2);
+
+ Err(self.error_form(
+ MachineError::type_error(
+ self.heap.h(),
+ ValidType::Integer,
+ n1,
+ ),
+ stub,
+ ))
+ }
+ }
+ }
+
+ pub(crate)
+ fn div(&self, n1: Number, n2: Number) -> Result<Number, MachineStub> {
+ let stub = MachineError::functor_stub(clause_name!("(/)"), 2);
+
+ if n2.is_zero() {
+ Err(self.error_form(MachineError::evaluation_error(EvalError::ZeroDivisor), stub))
+ } else {
+ try_numeric_result!(self, n1 / n2, stub)
+ }
+ }
+
+ pub(crate)
+ fn atan2(&self, n1: Number, n2: Number) -> Result<f64, MachineStub> {
+ let stub = MachineError::functor_stub(clause_name!("(is)"), 2);
+
+ if n1.is_zero() && n2.is_zero() {
+ Err(self.error_form(MachineError::evaluation_error(EvalError::Undefined), stub))
+ } else {
+ let f1 = self.float(n1)?;
+ let f2 = self.float(n2)?;
+
+ self.unary_float_fn_template(Number::Float(OrderedFloat(f1)), |f| f.atan2(f2))
+ }
+ }
+
+ pub(crate)
+ fn int_pow(&self, n1: Number, n2: Number) -> Result<Number, MachineStub> {
+ if n1.is_zero() && n2.is_negative() {
+ let stub = MachineError::functor_stub(clause_name!("(is)"), 2);
+ return Err(self.error_form(MachineError::evaluation_error(EvalError::Undefined), stub));
+ }
+
+ match (n1, n2) {
+ (Number::Integer(n1), Number::Integer(n2)) => {
+ if &*n1 != &1 && &*n2 < &0 {
+ let n = Number::Integer(n1);
+ let stub = MachineError::functor_stub(clause_name!("^"), 2);
+
+ Err(self.error_form(
+ MachineError::type_error(
+ self.heap.h(),
+ ValidType::Float,
+ n
+ ),
+ stub,
+ ))
+ } else {
+ Ok(Number::Integer(Rc::new(binary_pow(n1.as_ref().clone(), n2.as_ref()))))
+ }
+ }
+ (n1, Number::Integer(n2)) => {
+ let f1 = self.float(n1)?;
+ let f2 = self.float(Number::Integer(n2))?;
+
+ self.unary_float_fn_template(Number::Float(OrderedFloat(f1)), |f| f.powf(f2))
+ .map(|f| Number::Float(OrderedFloat(f)))
+ }
+ (n1, n2) => {
+ let f2 = self.float(n2)?;
+
+ if n1.is_negative() && f2 != f2.floor() {
+ let stub = MachineError::functor_stub(clause_name!("(is)"), 2);
+ return Err(
+ self.error_form(MachineError::evaluation_error(EvalError::Undefined), stub)
+ );
+ }
+
+ let f1 = self.float(n1)?;
+ self.unary_float_fn_template(Number::Float(OrderedFloat(f1)), |f| f.powf(f2))
+ .map(|f| Number::Float(OrderedFloat(f)))
+ }
+ }
+ }
+
+ pub(crate)
+ fn gcd(&self, n1: Number, n2: Number) -> Result<Integer, MachineStub> {
+ match (n1, n2) {
+ (Number::Integer(n1), Number::Integer(n2)) => {
+ Ok(Integer::from(n1.gcd_ref(&n2)))
+ }
+ (Number::Float(f), _) | (_, Number::Float(f)) => {
+ let n = Number::Float(f);
+ let stub = MachineError::functor_stub(clause_name!("gcd"), 2);
+
+ Err(self.error_form(
+ MachineError::type_error(
+ self.heap.h(),
+ ValidType::Integer,
+ n
+ ),
+ stub,
+ ))
+ }
+ (Number::Rational(r), _) | (_, Number::Rational(r)) => {
+ let n = Number::Rational(r);
+ let stub = MachineError::functor_stub(clause_name!("gcd"), 2);
+
+ Err(self.error_form(
+ MachineError::type_error(
+ self.heap.h(),
+ ValidType::Integer,
+ n,
+ ),
+ stub,
+ ))
+ }
+ }
+ }
+
+ pub(crate)
+ fn float_pow(&self, n1: Number, n2: Number) -> Result<Number, MachineStub> {
+ let f1 = result_f(&n1, rnd_f);
+ let f2 = result_f(&n2, rnd_f);
+
+ let stub = MachineError::functor_stub(clause_name!("(**)"), 2);
+
+ let f1 = try_numeric_result!(self, f1, stub)?;
+ let f2 = try_numeric_result!(self, f2, stub)?;
+
+ let result = result_f(&Number::Float(OrderedFloat(f1.powf(f2))), rnd_f);
+
+ Ok(Number::Float(OrderedFloat(try_numeric_result!(
+ self, result, stub
+ )?)))
+ }
+
+ pub(crate)
+ fn pow(&self, n1: Number, n2: Number, culprit: &'static str) -> Result<Number, MachineStub> {
+ if n2.is_negative() && n1.is_zero() {
+ let stub = MachineError::functor_stub(clause_name!(culprit), 2);
+ return Err(self.error_form(MachineError::evaluation_error(EvalError::Undefined), stub));
+ }
+
+ match (n1, n2) {
+ (Number::Integer(n1), Number::Integer(n2)) => {
+ Ok(Number::Integer(Rc::new(binary_pow(n1.as_ref().clone(), &*n2))))
+ }
+ (n1, n2) => {
+ self.float_pow(n1, n2)
+ }
+ }
+ }
+
+ pub(crate)
+ fn unary_float_fn_template<FloatFn>(&self, n1: Number, f: FloatFn) -> Result<f64, MachineStub>
+ where
+ FloatFn: Fn(f64) -> f64,
+ {
+ let stub = MachineError::functor_stub(clause_name!("(is)"), 2);
+
+ let f1 = try_numeric_result!(self, result_f(&n1, rnd_f), stub)?;
+ let f1 = result_f(&Number::Float(OrderedFloat(f(f1))), rnd_f);
+
+ try_numeric_result!(self, f1, stub)
+ }
+
+ pub(crate)
+ fn sin(&self, n1: Number) -> Result<f64, MachineStub> {
+ self.unary_float_fn_template(n1, |f| f.sin())
+ }
+
+ pub(crate)
+ fn cos(&self, n1: Number) -> Result<f64, MachineStub> {
+ self.unary_float_fn_template(n1, |f| f.cos())
+ }
+
+ pub(crate)
+ fn tan(&self, n1: Number) -> Result<f64, MachineStub> {
+ self.unary_float_fn_template(n1, |f| f.tan())
+ }
+
+ pub(crate)
+ fn log(&self, n1: Number) -> Result<f64, MachineStub> {
+ self.unary_float_fn_template(n1, |f| f.log(f64::consts::E))
+ }
+
+ pub(crate)
+ fn exp(&self, n1: Number) -> Result<f64, MachineStub> {
+ self.unary_float_fn_template(n1, |f| f.exp())
+ }
+
+ pub(crate)
+ fn asin(&self, n1: Number) -> Result<f64, MachineStub> {
+ self.unary_float_fn_template(n1, |f| f.asin())
+ }
+
+ pub(crate)
+ fn acos(&self, n1: Number) -> Result<f64, MachineStub> {
+ self.unary_float_fn_template(n1, |f| f.acos())
+ }
+
+ pub(crate)
+ fn atan(&self, n1: Number) -> Result<f64, MachineStub> {
+ self.unary_float_fn_template(n1, |f| f.atan())
+ }
+
+ pub(crate)
+ fn sqrt(&self, n1: Number) -> Result<f64, MachineStub> {
+ if n1.is_negative() {
+ let stub = MachineError::functor_stub(clause_name!("(is)"), 2);
+ return Err(self.error_form(MachineError::evaluation_error(EvalError::Undefined), stub));
+ }
+
+ self.unary_float_fn_template(n1, |f| f.sqrt())
+ }
+
+ pub(crate)
+ fn float(&self, n: Number) -> Result<f64, MachineStub> {
+ let stub = MachineError::functor_stub(clause_name!("(is)"), 2);
+ try_numeric_result!(self, result_f(&n, rnd_f), stub)
+ }
+
+ pub(crate)
+ fn floor(&self, n1: Number) -> Integer {
+ rnd_i(&n1).to_owned()
+ }
+
+ pub(crate)
+ fn ceiling(&self, n1: Number) -> Integer {
+ -self.floor(-n1)
+ }
+
+ pub(crate)
+ fn truncate(&self, n: Number) -> Integer {
+ if n.is_negative() {
+ -self.floor(n.abs())
+ } else {
+ self.floor(n)
+ }
+ }
+
+ pub(crate)
+ fn round(&self, n: Number) -> Result<Integer, MachineStub> {
+ let stub = MachineError::functor_stub(clause_name!("(is)"), 2);
+
+ let result = n + Number::Float(OrderedFloat(0.5f64));
+ let result = try_numeric_result!(self, result, stub)?;
+
+ Ok(self.floor(result))
+ }
+
+ pub(crate)
+ fn shr(&self, n1: Number, n2: Number) -> Result<Integer, MachineStub> {
+ let stub = MachineError::functor_stub(clause_name!("(>>)"), 2);
+
+ match (n1, n2) {
+ (Number::Integer(n1), Number::Integer(n2)) =>
+ match n2.to_u32() {
+ Some(n2) => Ok(Integer::from(&*n1 >> n2)),
+ _ => Ok(Integer::from(&*n1 >> u32::max_value())),
+ },
+ (Number::Integer(_), n2) => Err(self.error_form(
+ MachineError::type_error(
+ self.heap.h(),
+ ValidType::Integer,
+ n2,
+ ),
+ stub,
+ )),
+ (n1, _) => Err(self.error_form(
+ MachineError::type_error(
+ self.heap.h(),
+ ValidType::Integer,
+ n1,
+ ),
+ stub,
+ )),
+ }
+ }
+
+ pub(crate)
+ fn shl(&self, n1: Number, n2: Number) -> Result<Integer, MachineStub> {
+ let stub = MachineError::functor_stub(clause_name!("(<<)"), 2);
+
+ match (n1, n2) {
+ (Number::Integer(n1), Number::Integer(n2)) => match n2.to_u32() {
+ Some(n2) => Ok(Integer::from(&*n1 << n2)),
+ _ => Ok(Integer::from(&*n1 << u32::max_value())),
+ },
+ (Number::Integer(_), n2) => Err(self.error_form(
+ MachineError::type_error(
+ self.heap.h(),
+ ValidType::Integer,
+ n2,
+ ),
+ stub,
+ )),
+ (n1, _) => Err(self.error_form(
+ MachineError::type_error(
+ self.heap.h(),
+ ValidType::Integer,
+ n1,
+ ),
+ stub,
+ )),
+ }
+ }
+
+ pub(crate)
+ fn bitwise_complement(&self, n1: Number) -> Result<Integer, MachineStub> {
+ let stub = MachineError::functor_stub(clause_name!("(\\)"), 2);
+
+ match n1 {
+ Number::Integer(n1) => Ok(Integer::from(!&*n1)),
+ _ => Err(self.error_form(
+ MachineError::type_error(
+ self.heap.h(),
+ ValidType::Integer,
+ n1,
+ ),
+ stub,
+ )),
+ }
+ }
+
+ pub(crate)
+ fn xor(&self, n1: Number, n2: Number) -> Result<Integer, MachineStub> {
+ let stub = MachineError::functor_stub(clause_name!("(xor)"), 2);
+
+ match (n1, n2) {
+ (Number::Integer(n1), Number::Integer(n2)) => {
+ Ok(Integer::from(&*n1 ^ &*n2))
+ }
+ (Number::Integer(_), n2) => {
+ Err(self.error_form(
+ MachineError::type_error(
+ self.heap.h(),
+ ValidType::Integer,
+ n2
+ ),
+ stub,
+ ))
+ }
+ (n1, _) => {
+ Err(self.error_form(
+ MachineError::type_error(
+ self.heap.h(),
+ ValidType::Integer,
+ n1
+ ),
+ stub,
+ ))
+ }
+ }
+ }
+
+ pub(crate)
+ fn and(&self, n1: Number, n2: Number) -> Result<Integer, MachineStub> {
+ let stub = MachineError::functor_stub(clause_name!("(/\\)"), 2);
+
+ match (n1, n2) {
+ (Number::Integer(n1), Number::Integer(n2)) => Ok(Integer::from(&*n1 & &*n2)),
+ (Number::Integer(_), n2) => Err(self.error_form(
+ MachineError::type_error(
+ self.heap.h(),
+ ValidType::Integer,
+ n2,
+ ),
+ stub,
+ )),
+ (n1, _) => Err(self.error_form(
+ MachineError::type_error(
+ self.heap.h(),
+ ValidType::Integer,
+ n1,
+ ),
+ stub,
+ )),
+ }
+ }
+
+ pub(crate)
+ fn modulus(&self, x: Number, y: Number) -> Result<Integer, MachineStub> {
+ let stub = MachineError::functor_stub(clause_name!("(mod)"), 2);
+
+ match (x, y) {
+ (Number::Integer(x), Number::Integer(y)) => {
+ if &*y == &0 {
+ Err(self.error_form(
+ MachineError::evaluation_error(EvalError::ZeroDivisor),
+ stub,
+ ))
+ } else {
+ Ok(<(Integer, Integer)>::from(x.div_rem_floor_ref(&*y)).1)
+ }
+ }
+ (Number::Integer(_), n2) => Err(self.error_form(
+ MachineError::type_error(
+ self.heap.h(),
+ ValidType::Integer,
+ n2,
+ ),
+ stub,
+ )),
+ (n1, _) => Err(self.error_form(
+ MachineError::type_error(
+ self.heap.h(),
+ ValidType::Integer,
+ n1,
+ ),
+ stub,
+ )),
+ }
+ }
+
+ pub(crate)
+ fn max(&self, n1: Number, n2: Number) -> Result<Number, MachineStub> {
+ match (n1, n2) {
+ (Number::Integer(n1), Number::Integer(n2)) => {
+ if n1 > n2 {
+ Ok(Number::Integer(n1))
+ } else {
+ Ok(Number::Integer(n2))
+ }
+ }
+ (n1, n2) => {
+ let stub = MachineError::functor_stub(clause_name!("max"), 2);
+
+ let f1 = try_numeric_result!(self, result_f(&n1, rnd_f), stub)?;
+ let f2 = try_numeric_result!(self, result_f(&n2, rnd_f), stub)?;
+
+ Ok(Number::Float(cmp::max(OrderedFloat(f1), OrderedFloat(f2))))
+ }
+ }
+ }
+
+ pub(crate)
+ fn min(&self, n1: Number, n2: Number) -> Result<Number, MachineStub> {
+ match (n1, n2) {
+ (Number::Integer(n1), Number::Integer(n2)) => {
+ if n1 < n2 {
+ Ok(Number::Integer(n1))
+ } else {
+ Ok(Number::Integer(n2))
+ }
+ }
+ (n1, n2) => {
+ let stub = MachineError::functor_stub(clause_name!("max"), 2);
+
+ let f1 = try_numeric_result!(self, result_f(&n1, rnd_f), stub)?;
+ let f2 = try_numeric_result!(self, result_f(&n2, rnd_f), stub)?;
+
+ Ok(Number::Float(cmp::min(OrderedFloat(f1), OrderedFloat(f2))))
+ }
+ }
+ }
+
+ pub(crate)
+ fn sign(&self, n: Number) -> Integer {
+ if n.is_positive() {
+ Integer::from(1)
+ } else if n.is_negative() {
+ Integer::from(-1)
+ } else {
+ Integer::from(0)
+ }
+ }
+
+ pub(crate)
+ fn remainder(&self, n1: Number, n2: Number) -> Result<Integer, MachineStub> {
+ let stub = MachineError::functor_stub(clause_name!("(rem)"), 2);
+
+ match (n1, n2) {
+ (Number::Integer(n1), Number::Integer(n2)) => {
+ if &*n2 == &0 {
+ Err(self
+ .error_form(MachineError::evaluation_error(EvalError::ZeroDivisor), stub))
+ } else {
+ Ok(Integer::from(&*n1 % &*n2))
+ }
+ }
+ (Number::Integer(_), n2) => Err(self.error_form(
+ MachineError::type_error(
+ self.heap.h(),
+ ValidType::Integer,
+ n2,
+ ),
+ stub,
+ )),
+ (n1, _) => Err(self.error_form(
+ MachineError::type_error(
+ self.heap.h(),
+ ValidType::Integer,
+ n1,
+ ),
+ stub,
+ )),
+ }
+ }
+
+ pub(crate)
+ fn or(&self, n1: Number, n2: Number) -> Result<Integer, MachineStub> {
+ let stub = MachineError::functor_stub(clause_name!("(\\/)"), 2);
+
+ match (n1, n2) {
+ (Number::Integer(n1), Number::Integer(n2)) => {
+ Ok(Integer::from(&*n1 | &*n2))
+ }
+ (Number::Integer(_), n2) => {
+ Err(self.error_form(
+ MachineError::type_error(
+ self.heap.h(),
+ ValidType::Integer,
+ n2,
+ ),
+ stub,
+ ))
+ }
+ (n1, _) => {
+ Err(self.error_form(
+ MachineError::type_error(
+ self.heap.h(),
+ ValidType::Integer,
+ n1
+ ),
+ stub,
+ ))
+ }
+ }
+ }
+}
use crate::prolog::machine::*;
+use std::cmp::Ordering;
use std::vec::IntoIter;
pub static VERIFY_ATTRS: &str = include_str!("attributed_variables.pl");
.attr_var_init
.bindings
.iter()
- .map(|(ref h, _)| Addr::AttrVar(*h));
+ .map(|(ref h, _)| HeapCellValue::Addr(Addr::AttrVar(*h)));
let var_list_addr = Addr::HeapCell(self.heap.to_list(iter));
.attr_var_init
.bindings
.drain(0 ..)
- .map(|(_, addr)| addr);
+ .map(|(_, addr)| HeapCellValue::Addr(addr));
let value_list_addr = Addr::HeapCell(self.heap.to_list(iter));
(var_list_addr, value_list_addr)
})
.collect();
- attr_vars.sort_unstable_by(|a1, a2| self.compare_term_test(a1, a2));
+ attr_vars.sort_unstable_by(|a1, a2| {
+ self.compare_term_test(a1, a2).unwrap_or(Ordering::Less)
+ });
self.term_dedup(&mut attr_vars);
attr_vars.into_iter()
}
self.stack.index_and_frame_mut(e)[self.num_of_args + 1] =
- Addr::Con(Constant::CutPoint(self.b0));
+ Addr::CutPoint(self.b0);
self.stack.index_and_frame_mut(e)[self.num_of_args + 2] =
- Addr::Con(Constant::Usize(self.num_of_args));
+ Addr::Usize(self.num_of_args);
self.verify_attributes();
use crate::prolog::machine::machine_indices::*;
use crate::prolog::machine::stack::*;
+use crate::prolog::machine::streams::*;
+use std::mem;
use std::ops::IndexMut;
type Trail = Vec<(Ref, HeapCellValue)>;
StripAttributes
}
-pub(crate) trait CopierTarget: IndexMut<usize, Output = HeapCellValue> {
- fn threshold(&self) -> usize;
- fn push(&mut self, val: HeapCellValue);
- fn store(&self, val: Addr) -> Addr;
+pub(crate)
+trait CopierTarget: IndexMut<usize, Output = HeapCellValue> {
fn deref(&self, val: Addr) -> Addr;
+ fn push(&mut self, val: HeapCellValue);
fn stack(&mut self) -> &mut Stack;
+ fn store(&self, val: Addr) -> Addr;
+ fn threshold(&self) -> usize;
}
pub(crate)
*self.value_at_scan() = HeapCellValue::Addr(Addr::Lis(threshold));
let ra = self.target[addr].as_addr(threshold);
- let rd = self.target.store(self.target.deref(ra.clone()));
+ let rd = self.target.store(self.target.deref(ra));
- self.target.push(HeapCellValue::Addr(ra.clone()));
+ self.target.push(HeapCellValue::Addr(ra));
let hcv = HeapCellValue::Addr(self.target[addr + 1].as_addr(addr + 1));
self.target.push(hcv);
- match rd.clone() {
+ match rd {
Addr::AttrVar(h) | Addr::HeapCell(h)
if h >= self.old_h => {
self.target[threshold] = HeapCellValue::Addr(rd)
fn copy_partial_string(&mut self, addr: usize, n: usize) {
let threshold = self.target.threshold();
+ let tail_addr = self.target[addr + 1].as_addr(addr + 1);
+
+ let trail_item = mem::replace(
+ &mut self.target[addr + 1],
+ HeapCellValue::Addr(Addr::PStrLocation(threshold, 0)),
+ );
self.trail.push((
Ref::HeapCell(addr + 1),
- self.target[addr + 1].clone(),
+ trail_item,
));
- let tail_addr = self.target[addr + 1].as_addr(addr + 1);
-
- self.target[addr + 1] = HeapCellValue::Addr(
- Addr::PStrLocation(threshold, 0)
- );
-
let pstr =
match &self.target[addr] {
HeapCellValue::PartialString(ref pstr) => {
if let AttrVarPolicy::DeepCopy = self.attr_var_policy {
self.target.push(HeapCellValue::Addr(Addr::AttrVar(threshold)));
- let list_val = self.target[h + 1].clone();
+ let list_val = self.target[h + 1].context_free_clone();
self.target.push(list_val);
}
}
}
fn copy_var(&mut self, addr: Addr) {
- let rd = self.target.store(self.target.deref(addr.clone()));
+ let rd = self.target.store(self.target.deref(addr));
- match rd.clone() {
+ match rd {
Addr::AttrVar(h) | Addr::HeapCell(h) if h >= self.old_h => {
*self.value_at_scan() = HeapCellValue::Addr(rd);
self.scan += 1;
}
fn copy_structure(&mut self, addr: usize) {
- match self.target[addr].clone() {
+ match self.target[addr].context_free_clone() {
HeapCellValue::NamedStr(arity, name, fixity) => {
let threshold = self.target.threshold();
self.target.push(HeapCellValue::NamedStr(arity, name, fixity));
for i in 0..arity {
- let hcv = self.target[addr + 1 + i].clone();
+ let hcv = self.target[addr + 1 + i].context_free_clone();
self.target.push(hcv);
}
}
while self.scan < self.target.threshold() {
match self.value_at_scan() {
- HeapCellValue::NamedStr(..) => {
- self.scan += 1;
- }
- HeapCellValue::Addr(ref addr) => {
- match addr.clone() {
- Addr::Lis(addr) => {
- self.copy_list(addr);
+ &mut HeapCellValue::Addr(addr) => {
+ match addr {
+ Addr::Con(h) => {
+ self.target.push(self.target[h].context_free_clone());
+ self.scan += 1;
+ }
+ Addr::Stream(_) => {
+ self.target.push(HeapCellValue::Stream(Stream::null_stream()));
+ self.scan += 1;
+ }
+ Addr::Lis(h) => {
+ self.copy_list(h);
}
addr @ Addr::AttrVar(_)
| addr @ Addr::HeapCell(_)
Addr::PStrLocation(addr, n) => {
self.copy_partial_string_from(addr, n);
}
- Addr::Con(_) | Addr::DBRef(_) | Addr::Stream(_) => {
+ _ => {
self.scan += 1;
}
}
}
- HeapCellValue::PartialString(_) => {
+ _ => {
self.scan += 1;
}
}
let arity = self.machine_st[arity].clone();
let name = match self.machine_st.store(self.machine_st.deref(name)) {
- Addr::Con(Constant::Atom(name, _)) => name,
+ Addr::Con(h) =>
+ if let HeapCellValue::Atom(ref name, _) = &self.machine_st.heap[h] {
+ name.clone()
+ } else {
+ unreachable!()
+ },
_ => unreachable!(),
};
let arity = match self.machine_st.store(self.machine_st.deref(arity)) {
- Addr::Con(Constant::Integer(arity)) => arity.to_usize().unwrap(),
+ Addr::Con(h) =>
+ if let HeapCellValue::Integer(ref arity) = &self.machine_st.heap[h] {
+ arity.to_usize().unwrap()
+ } else {
+ unreachable!()
+ },
_ => unreachable!(),
};
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);
}
let module_addr = self.machine_st[module].clone();
let module_name = match self.machine_st.store(self.machine_st.deref(module_addr)) {
- Addr::Con(Constant::Atom(module, _)) => match self.indices.modules.get_mut(&module) {
- Some(ref mut module) => {
- module.code_dir.remove(&(name.clone(), arity));
- module.module_decl.name.clone()
- }
- _ => {
- self.machine_st.fail = true;
- return;
- }
- },
+ Addr::Con(h) =>
+ if let HeapCellValue::Atom(ref module, _) = &self.machine_st.heap[h] {
+ match self.indices.modules.get_mut(module) {
+ Some(ref mut module) => {
+ module.code_dir.remove(&(name.clone(), arity));
+ module.module_decl.name.clone()
+ }
+ _ => {
+ self.machine_st.fail = true;
+ return;
+ }
+ }
+ } else {
+ unreachable!()
+ },
_ => unreachable!(),
};
place.push_to_queue(&mut addrs, added_clause);
self.print_new_dynamic_clause(addrs, name.clone(), arity)
}
- Err(err) => return self.machine_st.throw_exception(err),
+ Err(err) => {
+ return self.machine_st.throw_exception(err);
+ }
};
- self.handle_eval_result_from_dynamic_compile(pred_str, name, arity, place.predicate_name());
+ self.handle_eval_result_from_dynamic_compile(
+ pred_str,
+ name,
+ arity,
+ place.predicate_name(),
+ );
}
fn set_module_atom_tbl(&mut self, module_addr: Addr, name: &mut ClauseName) -> bool {
let atom_tbl = match self.machine_st.store(self.machine_st.deref(module_addr)) {
- Addr::Con(Constant::Atom(module, _)) => match self.indices.modules.get(&module) {
- Some(ref module) => module.atom_tbl.clone(),
- None => {
+ Addr::Con(h) =>
+ if let HeapCellValue::Atom(ref module, _) = &self.machine_st.heap[h] {
+ match self.indices.modules.get(module) {
+ Some(ref module) => module.atom_tbl.clone(),
+ None => {
+ self.machine_st.fail = true;
+ return false;
+ }
+ }
+ } else {
self.machine_st.fail = true;
return false;
- }
- },
+ },
_ => unreachable!(),
};
fn retract_from_dynamic_predicate_in_module(&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(Constant::Integer(n)) => n.to_usize().unwrap(),
+ Addr::Con(h) =>
+ if let HeapCellValue::Integer(ref n) = &self.machine_st.heap[h] {
+ n.to_usize().unwrap()
+ } else {
+ unreachable!()
+ },
_ => unreachable!(),
};
self.print_new_dynamic_clause(addrs, name.clone(), arity)
}
- Err(err) => return self.machine_st.throw_exception(err),
+ Err(err) => {
+ return self.machine_st.throw_exception(err);
+ }
};
self.handle_eval_result_from_dynamic_compile(
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(Constant::Integer(n)) => n.to_usize().unwrap(),
- _ => unreachable!(),
+ Addr::Con(h) =>
+ if let HeapCellValue::Integer(n) = &self.machine_st.heap[h] {
+ n.to_usize().unwrap()
+ } else {
+ unreachable!()
+ },
+ _ => {
+ unreachable!()
+ }
};
let (name, arity) = self.get_predicate_key(temp_v!(1), temp_v!(2));
self.print_new_dynamic_clause(addrs, name.clone(), arity)
}
- Err(err) => return self.machine_st.throw_exception(err),
+ Err(err) => {
+ return self.machine_st.throw_exception(err);
+ }
};
self.handle_eval_result_from_dynamic_compile(
use core::marker::PhantomData;
-use crate::prolog_parser::ast::*;
+use crate::prolog_parser::ast::Constant;
use crate::prolog::machine::machine_indices::*;
use crate::prolog::machine::partial_string::*;
#[inline]
pub(crate)
- fn push(&mut self, val: HeapCellValue) {
+ fn clone(&self, h: usize) -> HeapCellValue {
+ match &self[h] {
+ &HeapCellValue::Addr(addr) => {
+ HeapCellValue::Addr(addr)
+ }
+ &HeapCellValue::Atom(ref name, ref op) => {
+ HeapCellValue::Atom(name.clone(), op.clone())
+ }
+ &HeapCellValue::DBRef(ref db_ref) => {
+ HeapCellValue::DBRef(db_ref.clone())
+ }
+ &HeapCellValue::Integer(ref n) => {
+ HeapCellValue::Integer(n.clone())
+ }
+ &HeapCellValue::NamedStr(arity, ref name, ref op) => {
+ HeapCellValue::NamedStr(arity, name.clone(), op.clone())
+ }
+ &HeapCellValue::Rational(ref r) => {
+ HeapCellValue::Rational(r.clone())
+ }
+ &HeapCellValue::PartialString(_) => {
+ HeapCellValue::Addr(Addr::PStrLocation(h, 0))
+ }
+ &HeapCellValue::Stream(_) => {
+ HeapCellValue::Addr(Addr::Stream(h))
+ }
+ }
+ }
+
+ #[inline]
+ pub(crate)
+ fn put_constant(&mut self, c: Constant) -> Addr {
+ match c {
+ Constant::Atom(name, op) => {
+ Addr::Con(self.push(HeapCellValue::Atom(name, op)))
+ }
+ Constant::Char(c) => {
+ self.push(HeapCellValue::Addr(Addr::Char(c)));
+ Addr::Char(c)
+ }
+ Constant::CharCode(c) => {
+ self.push(HeapCellValue::Addr(Addr::CharCode(c)));
+ Addr::CharCode(c)
+ }
+ Constant::CutPoint(cp) => {
+ self.push(HeapCellValue::Addr(Addr::CutPoint(cp)));
+ Addr::CutPoint(cp)
+ }
+ Constant::EmptyList => {
+ self.push(HeapCellValue::Addr(Addr::EmptyList));
+ Addr::EmptyList
+ }
+ Constant::Integer(n) => {
+ Addr::Con(self.push(HeapCellValue::Integer(n)))
+ }
+ Constant::Rational(r) => {
+ Addr::Con(self.push(HeapCellValue::Rational(r)))
+ }
+ Constant::Float(f) => {
+ self.push(HeapCellValue::Addr(Addr::Float(f)));
+ Addr::Float(f)
+ }
+ Constant::String(s) => {
+ let addr = self.allocate_pstr(&s);
+ let h = self.h();
+
+ self[h - 1] = HeapCellValue::Addr(Addr::EmptyList);
+ addr
+ }
+ Constant::Usize(n) => {
+ self.push(HeapCellValue::Addr(Addr::Usize(n)));
+ Addr::Usize(n)
+ }
+ }
+ }
+
+ #[inline]
+ pub(crate)
+ fn push(&mut self, val: HeapCellValue) -> usize {
+ let h = self.h();
+
unsafe {
let new_top = self.buf.new_block(mem::size_of::<HeapCellValue>());
ptr::write(self.buf.top as *mut _, val);
self.buf.top = new_top;
}
+
+ h
+ }
+
+ #[inline]
+ pub(crate)
+ fn rational_at(&self, h: usize) -> bool {
+ if let HeapCellValue::Rational(_) = &self[h] {
+ true
+ } else {
+ false
+ }
+ }
+
+ #[inline]
+ pub(crate)
+ fn integer_at(&self, h: usize) -> bool {
+ if let HeapCellValue::Integer(_) = &self[h] {
+ true
+ } else {
+ false
+ }
+ }
+
+ #[inline]
+ pub(crate)
+ fn atom_at(&self, h: usize) -> bool {
+ if let HeapCellValue::Atom(..) = &self[h] {
+ true
+ } else {
+ false
+ }
}
#[inline]
pub(crate)
- fn allocate_pstr(&mut self, mut src: &str) -> Option<Addr> {
+ fn to_unifiable(&mut self, non_heap_value: HeapCellValue) -> Addr {
+ match non_heap_value {
+ HeapCellValue::Addr(addr) => {
+ addr
+ }
+ val @ HeapCellValue::Atom(..)
+ | val @ HeapCellValue::Integer(_)
+ | val @ HeapCellValue::DBRef(_)
+ | val @ HeapCellValue::Rational(_) => {
+ Addr::Con(self.push(val))
+ }
+ val @ HeapCellValue::NamedStr(..) => {
+ Addr::Str(self.push(val))
+ }
+ val @ HeapCellValue::Stream(..) => {
+ Addr::Stream(self.push(val))
+ }
+ val @ HeapCellValue::PartialString(_) => {
+ let h = self.push(val);
+ self.push(HeapCellValue::Addr(Addr::EmptyList));
+
+ Addr::Con(h)
+ }
+ }
+ }
+
+ #[inline]
+ pub(crate)
+ fn allocate_pstr(&mut self, src: &str) -> Addr {
+ self.write_pstr(src)
+ .unwrap_or_else(|| {
+ let h = self.h();
+
+ self.push(HeapCellValue::PartialString(
+ PartialString::empty()
+ ));
+
+ self.push(HeapCellValue::Addr(
+ Addr::HeapCell(h + 1)
+ ));
+
+ Addr::PStrLocation(h, 0)
+ })
+ }
+
+ #[inline]
+ fn write_pstr(&mut self, mut src: &str) -> Option<Addr> {
let orig_h = self.h();
loop {
}
pub(crate)
- fn to_list<Iter: Iterator<Item = Addr>>(&mut self, values: Iter) -> usize {
+ fn to_list<Iter, SrcT>(&mut self, values: Iter) -> usize
+ where Iter: Iterator<Item = SrcT>,
+ SrcT: Into<HeapCellValue>
+ {
let head_addr = self.h();
+ let mut h = head_addr;
- for value in values {
- let h = self.h();
-
+ for value in values.map(|v| v.into()) {
self.push(HeapCellValue::Addr(Addr::Lis(h + 1)));
- self.push(HeapCellValue::Addr(value));
+ self.push(value);
+
+ h += mem::size_of::<HeapCellValue>() * 2;
}
- self.push(HeapCellValue::Addr(Addr::Con(Constant::EmptyList)));
+ self.push(HeapCellValue::Addr(Addr::EmptyList));
head_addr
}
pub(crate)
fn to_local_code_ptr(&self, addr: &Addr) -> Option<LocalCodePtr> {
let extract_integer = |s: usize| -> Option<usize> {
- match self[s].as_addr(s) {
- Addr::Con(Constant::Integer(n)) => n.to_usize(),
+ match &self[s] {
+ &HeapCellValue::Integer(ref n) => n.to_usize(),
_ => None
}
};
_ => None
}
}
+
+ #[inline]
+ pub
+ fn index_addr<'a>(&'a self, addr: &Addr) -> RefOrOwned<'a, HeapCellValue> {
+ match addr {
+ &Addr::Con(h) | &Addr::Str(h) | &Addr::Stream(h) => {
+ RefOrOwned::Borrowed(&self[h])
+ }
+ addr => {
+ RefOrOwned::Owned(HeapCellValue::Addr(*addr))
+ }
+ }
+ }
}
impl<T: RawBlockTraits> Index<usize> for HeapTemplate<T> {
use prolog_parser::ast::*;
-use crate::prolog::forms::PredicateKey;
+use crate::prolog::forms::{Number, PredicateKey};
+use crate::prolog::machine::heap::*;
use crate::prolog::machine::machine_indices::*;
use crate::prolog::machine::machine_state::*;
use crate::prolog::rug::Integer;
from: ErrorProvenance,
}
-impl MachineError {
- pub(super) fn functor_stub(name: ClauseName, arity: usize) -> MachineStub {
- let name = HeapCellValue::Addr(Addr::Con(Constant::Atom(name, None)));
- functor!(
- "/",
- 2,
- [name, heap_integer!(Integer::from(arity))],
- SharedOpDesc::new(400, YFX)
- )
+pub(super)
+trait TypeError {
+ fn type_error(self, h: usize, valid_type: ValidType) -> MachineError;
+}
+
+impl TypeError for Addr {
+ fn type_error(self, _: usize, valid_type: ValidType) -> MachineError {
+ let stub = functor!(
+ "type_error",
+ [atom(valid_type.as_str()), addr(self)]
+ );
+
+ MachineError {
+ stub,
+ location: None,
+ from: ErrorProvenance::Received
+ }
}
+}
+
+impl TypeError for MachineStub {
+ fn type_error(self, h: usize, valid_type: ValidType) -> MachineError {
+ let stub = functor!(
+ "type_error",
+ [atom(valid_type.as_str()), aux(h, 0)],
+ [self]
+ );
- pub(super) fn evaluation_error(eval_error: EvalError) -> Self {
- let stub = functor!("evaluation_error", 1, [heap_atom!(eval_error.as_str())]);
MachineError {
stub,
location: None,
- from: ErrorProvenance::Received,
+ from: ErrorProvenance::Constructed
}
}
+}
- pub(super)
- fn type_error(valid_type: ValidType, culprit: Addr) -> Self {
+impl TypeError for Number {
+ fn type_error(self, _h: usize, valid_type: ValidType) -> MachineError {
let stub = functor!(
"type_error",
- 2,
- [
- heap_atom!(valid_type.as_str()),
- HeapCellValue::Addr(culprit)
- ]
+ [atom(valid_type.as_str()), number(self)]
+ );
+
+ MachineError {
+ stub,
+ location: None,
+ from: ErrorProvenance::Received
+ }
+ }
+}
+
+pub(super)
+trait PermissionError {
+ fn permission_error(self, h: usize, index_str: &'static str, perm: Permission) -> MachineError;
+}
+
+impl PermissionError for Addr {
+ fn permission_error(self, _: usize, index_str: &'static str, perm: Permission) -> MachineError {
+ let stub = functor!(
+ "permission_error",
+ [atom(perm.as_str()), atom(index_str), addr(self)]
+ );
+
+ MachineError {
+ stub,
+ location: None,
+ from: ErrorProvenance::Received
+ }
+ }
+}
+
+impl PermissionError for MachineStub {
+ fn permission_error(self, h: usize, index_str: &'static str, perm: Permission) -> MachineError {
+ let stub = functor!(
+ "permission_error",
+ [atom(perm.as_str()), atom(index_str), aux(h, 0)],
+ [self]
+ );
+
+ MachineError {
+ stub,
+ location: None,
+ from: ErrorProvenance::Constructed
+ }
+ }
+}
+
+pub(super)
+trait DomainError {
+ fn domain_error(self, error: DomainErrorType) -> MachineError;
+}
+
+impl DomainError for Addr {
+ fn domain_error(self, error: DomainErrorType) -> MachineError {
+ let stub = functor!(
+ "domain_error",
+ [atom(error.as_str()), addr(self)]
+ );
+
+ MachineError {
+ stub,
+ location: None,
+ from: ErrorProvenance::Received,
+ }
+ }
+}
+
+impl DomainError for Number {
+ fn domain_error(self, error: DomainErrorType) -> MachineError {
+ let stub = functor!(
+ "domain_error",
+ [atom(error.as_str()), number(self)]
);
MachineError {
from: ErrorProvenance::Received,
}
}
+}
+
+impl MachineError {
+ pub(super) fn functor_stub(name: ClauseName, arity: usize) -> MachineStub {
+ functor!(
+ "/",
+ SharedOpDesc::new(400, YFX),
+ [clause_name(name), integer(arity)]
+ )
+ }
+
+ pub(super) fn evaluation_error(eval_error: EvalError) -> Self {
+ let stub = functor!("evaluation_error", [atom(eval_error.as_str())]);
+
+ MachineError {
+ stub,
+ location: None,
+ from: ErrorProvenance::Received,
+ }
+ }
+
+ pub(super)
+ fn type_error<T: TypeError>(h: usize, valid_type: ValidType, culprit: T) -> Self {
+ culprit.type_error(h, valid_type)
+ }
pub(super)
fn module_resolution_error(
name: ClauseName,
arity: usize,
) -> Self {
- let mod_name = HeapCellValue::Addr(Addr::Con(Constant::Atom(mod_name, None)));
- let name = HeapCellValue::Addr(Addr::Con(Constant::Atom(name, None)));
-
- let mut stub = functor!(
- "evaluation_error",
- 1,
- [HeapCellValue::Addr(Addr::HeapCell(h + 2))]
+ let res_stub = functor!(
+ ":",
+ SharedOpDesc::new(600, XFY),
+ [clause_name(mod_name), clause_name(name)]
);
- stub.append(&mut functor!(
+ let ind_stub = functor!(
"/",
- 2,
- [
- HeapCellValue::Addr(Addr::HeapCell(h + 2 + 3)),
- heap_integer!(Integer::from(arity))
- ],
- SharedOpDesc::new(400, YFX)
- ));
-
- stub.append(&mut functor!(
- ":",
- 2,
- [mod_name, name],
- SharedOpDesc::new(600, XFY)
- ));
+ SharedOpDesc::new(400, YFX),
+ [aux(h + 2, 0), integer(arity)],
+ [res_stub]
+ );
+
+ let stub = functor!(
+ "evaluation_error",
+ [aux(h, 0)],
+ [ind_stub]
+ );
MachineError {
stub,
fn existence_error(h: usize, err: ExistenceError) -> Self {
match err {
ExistenceError::Module(name) => {
- let name = HeapCellValue::Addr(Addr::Con(Constant::Atom(name, None)));
- let stub = functor!("existence_error", 2, [heap_atom!("module"), name]);
+ let stub = functor!(
+ "existence_error",
+ [atom("module"), clause_name(name)]
+ );
MachineError {
stub,
location: None,
- from: ErrorProvenance::Constructed,
+ from: ErrorProvenance::Received,
}
}
ExistenceError::Procedure(name, arity) => {
- let mut stub = functor!(
- "existence_error",
- 2,
- [heap_atom!("procedure"), heap_str!(3 + h)]
+ let culprit = functor!(
+ "/",
+ SharedOpDesc::new(400, YFX),
+ [clause_name(name), integer(arity)]
);
- stub.append(&mut Self::functor_stub(name, arity));
+ let stub = functor!(
+ "existence_error",
+ [atom("procedure"), aux(h, 0)],
+ [culprit]
+ );
MachineError {
stub,
from: ErrorProvenance::Constructed,
}
}
- ExistenceError::Stream(addr) => {
- let culprit = HeapCellValue::Addr(addr);
- let stub = functor!("existence_error", 2, [heap_atom!("stream"), culprit]);
+ ExistenceError::Stream(culprit) => {
+ let stub = functor!(
+ "existence_error",
+ [atom("stream"), addr(culprit)]
+ );
MachineError {
stub,
location: None,
- from: ErrorProvenance::Constructed,
+ from: ErrorProvenance::Received,
}
}
}
}
pub(super)
- fn session_error(h: usize, err: SessionError) -> Self {
+ fn permission_error<T: PermissionError>(
+ h: usize,
+ err: Permission,
+ index_str: &'static str,
+ culprit: T,
+ ) -> Self {
+ culprit.permission_error(
+ h,
+ index_str,
+ err,
+ )
+ }
+
+ fn arithmetic_error(h: usize, err: ArithmeticError) -> Self {
match err {
- SessionError::ParserError(err) => Self::syntax_error(h, err),
- SessionError::CannotOverwriteBuiltIn(pred_str)
- | SessionError::CannotOverwriteImport(pred_str) => {
- Self::permission_error(
- PermissionError::Modify,
- "private_procedure",
- Addr::Con(Constant::Atom(pred_str, None)),
- )
+ ArithmeticError::UninstantiatedVar => {
+ Self::instantiation_error()
}
- SessionError::InvalidFileName(filename) => {
- Self::existence_error(h, ExistenceError::Module(filename))
- }
- SessionError::ModuleDoesNotContainExport(..) => Self::permission_error(
- PermissionError::Access,
- "private_procedure",
- Addr::Con(atom!("module_does_not_contain_claimed_export")),
- ),
- SessionError::ModuleNotFound => Self::permission_error(
- PermissionError::Access,
- "private_procedure",
- Addr::Con(atom!("module_does_not_exist")),
- ),
- SessionError::OpIsInfixAndPostFix(op) => {
- Self::permission_error(
- PermissionError::Create,
- "operator",
- Addr::Con(Constant::Atom(op, None)),
- )
+ ArithmeticError::NonEvaluableFunctor(name, arity) => {
+ let culprit = functor!(
+ "/",
+ SharedOpDesc::new(400, YFX),
+ [constant(h, &name), integer(arity)]
+ );
+
+ Self::type_error(h, ValidType::Evaluable, culprit)
}
- _ => unreachable!(),
}
}
+ #[inline]
pub(super)
- fn permission_error(
- err: PermissionError,
- index_str: &'static str,
- culprit: Addr,
- ) -> Self {
- let culprit = HeapCellValue::Addr(culprit);
-
- let err = vec![heap_atom!(err.as_str()), heap_atom!(index_str), culprit];
- let mut stub = functor!("permission_error", 3);
-
- stub.extend(err.into_iter());
+ fn domain_error<T: DomainError>(error: DomainErrorType, culprit: T) -> Self {
+ culprit.domain_error(error)
+ }
+
+ pub(super)
+ fn instantiation_error() -> Self {
+ let stub = functor!("instantiation_error");
MachineError {
stub,
location: None,
- from: ErrorProvenance::Constructed,
+ from: ErrorProvenance::Received,
}
}
- fn arithmetic_error(h: usize, err: ArithmeticError) -> Self {
+ pub(super)
+ fn session_error(h: usize, err: SessionError) -> Self {
match err {
- ArithmeticError::UninstantiatedVar => Self::instantiation_error(),
- ArithmeticError::NonEvaluableFunctor(name, arity) => {
- let name = HeapCellValue::Addr(Addr::Con(name));
- let culprit = functor!(
- "/",
- 2,
- [name, heap_integer!(Integer::from(arity))],
- SharedOpDesc::new(400, YFX)
- );
-
- let mut stub = Self::type_error(ValidType::Evaluable, Addr::HeapCell(3 + h)).stub;
- stub.extend(culprit.into_iter());
-
- MachineError {
- stub,
- location: None,
- from: ErrorProvenance::Constructed,
- }
+ SessionError::ParserError(err) => {
+ Self::syntax_error(h, err)
}
+ SessionError::CannotOverwriteBuiltIn(pred_str)
+ | SessionError::CannotOverwriteImport(pred_str) => {
+ Self::permission_error(
+ h,
+ Permission::Modify,
+ "private_procedure",
+ functor!(clause_name(pred_str)),
+ )
+ }
+ SessionError::InvalidFileName(filename) => {
+ Self::existence_error(h, ExistenceError::Module(filename))
+ }
+ SessionError::ModuleDoesNotContainExport(..) => {
+ Self::permission_error(
+ h,
+ Permission::Access,
+ "private_procedure",
+ functor!("module_does_not_contain_claimed_export"),
+ )
+ }
+ SessionError::ModuleNotFound => {
+ Self::permission_error(
+ h,
+ Permission::Access,
+ "private_procedure",
+ functor!("modules_does_not_exist"),
+ )
+ }
+ SessionError::OpIsInfixAndPostFix(op) => {
+ Self::permission_error(
+ h,
+ Permission::Create,
+ "operator",
+ functor!(clause_name(op)),
+ )
+ }
+ _ => unreachable!(),
}
}
}
let location = err.line_and_col_num();
- let err = vec![heap_atom!(err.as_str())];
-
- let mut stub = if err.len() == 1 {
- functor!("syntax_error", 1)
- } else {
- functor!("syntax_error", 1, [heap_str!(h + 2)])
- };
-
- stub.extend(err.into_iter());
-
- MachineError {
- stub,
- location,
- from: ErrorProvenance::Constructed,
- }
- }
-
- pub(super)
- fn domain_error(error: DomainError, culprit: Addr) -> Self {
+ let stub = functor!(err.as_str());
+
let stub = functor!(
- "domain_error",
- 2,
- [heap_atom!(error.as_str()), HeapCellValue::Addr(culprit)]
+ "syntax_error",
+ [aux(h, 0)],
+ [stub]
);
- MachineError {
- stub,
- location: None,
- from: ErrorProvenance::Received,
- }
- }
- pub(super)
- fn instantiation_error() -> Self {
- let stub = functor!("instantiation_error");
MachineError {
stub,
- location: None,
- from: ErrorProvenance::Received,
+ location,
+ from: ErrorProvenance::Constructed,
}
}
pub(super)
fn representation_error(flag: RepFlag) -> Self {
- let stub = functor!("representation_error", 1, [heap_atom!(flag.as_str())]);
+ let stub = functor!("representation_error", [atom(flag.as_str())]);
+
MachineError {
stub,
location: None,
}
#[derive(Clone, Copy)]
-pub enum PermissionError {
+pub enum Permission {
Access,
Create,
InputStream,
OutputStream,
}
-impl PermissionError {
+impl Permission {
pub fn as_str(self) -> &'static str {
match self {
- PermissionError::Access => "access",
- PermissionError::Create => "create",
- PermissionError::InputStream => "input",
- PermissionError::Modify => "modify",
- PermissionError::OutputStream => "output",
+ Permission::Access => "access",
+ Permission::Create => "create",
+ Permission::InputStream => "input",
+ Permission::Modify => "modify",
+ Permission::OutputStream => "output",
}
}
}
}
#[derive(Clone, Copy)]
-pub enum DomainError {
+pub enum DomainErrorType {
NotLessThanZero,
Stream,
StreamOrAlias,
}
-impl DomainError {
+impl DomainErrorType {
pub fn as_str(self) -> &'static str {
match self {
- DomainError::NotLessThanZero => "not_less_than_zero",
- DomainError::Stream => "stream",
- DomainError::StreamOrAlias => "stream_or_alias",
+ DomainErrorType::NotLessThanZero => "not_less_than_zero",
+ DomainErrorType::Stream => "stream",
+ DomainErrorType::StreamOrAlias => "stream_or_alias",
}
}
}
}
// used by '$skip_max_list'.
+#[derive(Clone, Copy)]
pub(super) enum CycleSearchResult {
EmptyList,
NotList,
- PartialList(usize, Ref), // the list length (up to max), and an offset into the heap.
- ProperList(usize), // the list length.
- CompleteString(usize, Rc<String>), // the string length (in bytes), the string.
- UntouchedString(usize, Rc<String>), // the cut off, past which is the untouched string.
+ PartialList(usize, Ref), // the list length (up to max), and an offset into the heap.
+ ProperList(usize), // the list length.
PStrLocation(usize, usize, usize), // the list length (up to max), the heap offset, byte offset into the string.
- UntouchedList(usize), // the address of an uniterated Addr::Lis(address).
+ UntouchedList(usize), // the address of an uniterated Addr::Lis(address).
}
impl MachineState {
// see 8.4.3 of Draft Technical Corrigendum 2.
- pub(super) fn check_sort_errors(&self) -> CallResult {
+ pub(super)
+ fn check_sort_errors(&self) -> CallResult {
let stub = MachineError::functor_stub(clause_name!("sort"), 2);
let list = self.store(self.deref(self[temp_v!(1)].clone()));
let sorted = self.store(self.deref(self[temp_v!(2)].clone()));
return Err(self.error_form(MachineError::instantiation_error(), stub))
}
CycleSearchResult::NotList => {
- return Err(self.error_form(MachineError::type_error(ValidType::List, list), stub))
+ return Err(self.error_form(MachineError::type_error(0, ValidType::List, list), stub))
}
_ => {}
};
match self.detect_cycles(sorted.clone()) {
CycleSearchResult::NotList if !sorted.is_ref() => {
- Err(self.error_form(MachineError::type_error(ValidType::List, sorted), stub))
+ Err(self.error_form(MachineError::type_error(0, ValidType::List, sorted), stub))
}
_ => Ok(()),
}
match self.detect_cycles(list.clone()) {
CycleSearchResult::NotList if !list.is_ref() => {
- Err(self.error_form(MachineError::type_error(ValidType::List, list), stub))
+ Err(self.error_form(MachineError::type_error(0, ValidType::List, list), stub))
}
_ => {
let mut addr = list;
let mut new_l = l;
loop {
- match self.heap[new_l].clone() {
- HeapCellValue::Addr(Addr::Str(l)) => new_l = l,
+ match self.heap.clone(new_l) {
+ HeapCellValue::Addr(Addr::Str(l)) => {
+ new_l = l;
+ }
HeapCellValue::NamedStr(2, ref name, Some(_))
- if name.as_str() == "-" =>
- {
- break
+ if name.as_str() == "-" => {
+ break;
+ }
+ HeapCellValue::Addr(Addr::HeapCell(_)) => {
+ break;
+ }
+ HeapCellValue::Addr(Addr::StackCell(..)) => {
+ break;
}
- HeapCellValue::Addr(Addr::HeapCell(_)) => break,
- HeapCellValue::Addr(Addr::StackCell(..)) => break,
_ => {
return Err(self.error_form(
- MachineError::type_error(ValidType::Pair, Addr::HeapCell(l)),
+ MachineError::type_error(0, ValidType::Pair, Addr::HeapCell(l)),
stub,
))
}
}
// see 8.4.4 of Draft Technical Corrigendum 2.
- pub(super) fn check_keysort_errors(&self) -> CallResult {
+ pub(super)
+ fn check_keysort_errors(&self) -> CallResult {
let stub = MachineError::functor_stub(clause_name!("keysort"), 2);
- let pairs = self.store(self.deref(self[temp_v!(1)].clone()));
+
+ let pairs = self.store(self.deref(self[temp_v!(1)].clone()));
let sorted = self.store(self.deref(self[temp_v!(2)].clone()));
match self.detect_cycles(pairs.clone()) {
Err(self.error_form(MachineError::instantiation_error(), stub))
}
CycleSearchResult::NotList => {
- Err(self.error_form(MachineError::type_error(ValidType::List, pairs), stub))
+ Err(self.error_form(MachineError::type_error(0, ValidType::List, pairs), stub))
}
_ => Ok(()),
}?;
self.check_for_list_pairs(sorted)
}
- pub(super) fn error_form(&self, err: MachineError, src: MachineStub) -> MachineStub {
+ pub(super)
+ fn error_form(&self, err: MachineError, src: MachineStub) -> MachineStub {
let location = err.location;
let err_len = err.len();
if let Some((line_num, _)) = location {
let colon_op_desc = Some(SharedOpDesc::new(600, XFY));
- stub.extend(
- vec![
- HeapCellValue::NamedStr(2, clause_name!(":"), colon_op_desc),
- HeapCellValue::Addr(Addr::HeapCell(h + 6 + err_len)),
- heap_integer!(Integer::from(line_num)),
- ]
- .into_iter(),
- );
+ stub.push(HeapCellValue::NamedStr(2, clause_name!(":"), colon_op_desc));
+ stub.push(HeapCellValue::Addr(Addr::HeapCell(h + 6 + err_len)));
+ stub.push(HeapCellValue::Integer(Rc::new(Integer::from(line_num))));
}
stub.extend(src.into_iter());
stub
}
- pub(super) fn throw_exception(&mut self, err: MachineStub) {
+ pub(super)
+ fn throw_exception(&mut self, err: MachineStub) {
let h = self.heap.h();
self.ball.boundary = 0;
fn from(err: ParserError) -> Self {
EvalSession::from(SessionError::ParserError(err))
}
+
}
use crate::prolog::machine::code_repo::CodeRepo;
use crate::prolog::machine::Ball;
use crate::prolog::machine::heap::*;
+use crate::prolog::machine::machine_state::*;
use crate::prolog::machine::partial_string::*;
use crate::prolog::machine::raw_block::RawBlockTraits;
use crate::prolog::machine::streams::Stream;
use crate::prolog::instructions::*;
-use crate::prolog::rug::Integer;
+use crate::prolog::ordered_float::OrderedFloat;
+use crate::prolog::rug::{Integer, Rational};
use indexmap::IndexMap;
),
}
-#[derive(Clone, PartialEq, Eq, Hash)]
+// 7.2
+#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
+pub enum TermOrderCategory {
+ Variable,
+ FloatingPoint,
+ Integer,
+ Atom,
+ Compound,
+}
+
+#[derive(Clone, Copy, PartialEq, Eq, Hash)]
pub enum Addr {
AttrVar(usize),
- Con(Constant),
- DBRef(DBRef),
+ Char(char),
+ CharCode(u32),
+ Con(usize),
+ CutPoint(usize),
+ EmptyList,
+ Float(OrderedFloat<f64>),
Lis(usize),
HeapCell(usize),
+ PStrLocation(usize, usize), // location of pstr in heap, offset into string in bytes.
StackCell(usize, usize),
Str(usize),
- PStrLocation(usize, usize), // location of pstr in heap, offset into string in bytes.
- Stream(Stream),
+ Stream(usize),
+ Usize(usize),
}
-#[derive(Clone, Copy, Hash, Eq, PartialEq)]
+#[derive(Clone, Copy, Hash, Eq, PartialEq, PartialOrd)]
pub enum Ref {
AttrVar(usize),
HeapCell(usize),
}
}
+impl Ord for Ref {
+ fn cmp(&self, other: &Ref) -> Ordering {
+ match (self, other) {
+ (Ref::AttrVar(h1), Ref::AttrVar(h2))
+ | (Ref::HeapCell(h1), Ref::HeapCell(h2))
+ | (Ref::HeapCell(h1), Ref::AttrVar(h2))
+ | (Ref::AttrVar(h1), Ref::HeapCell(h2)) => {
+ h1.cmp(&h2)
+ }
+ (Ref::StackCell(fr1, sc1), Ref::StackCell(fr2, sc2)) => {
+ fr1.cmp(&fr2).then_with(|| sc1.cmp(&sc2))
+ }
+ (Ref::StackCell(..), _) => {
+ Ordering::Greater
+ }
+ (_, Ref::StackCell(..)) => {
+ Ordering::Less
+ }
+ }
+ }
+}
+
impl PartialEq<Ref> for Addr {
fn eq(&self, r: &Ref) -> bool {
self.as_var() == Some(*r)
}
}
+ pub(super)
+ fn order_category(&self, heap: &Heap) -> Option<TermOrderCategory> {
+ match self {
+ Addr::HeapCell(_) | Addr::AttrVar(_) | Addr::StackCell(..) => {
+ Some(TermOrderCategory::Variable)
+ }
+ Addr::Float(_) => {
+ Some(TermOrderCategory::FloatingPoint)
+ }
+ &Addr::Con(h) => {
+ match &heap[h] {
+ HeapCellValue::Atom(..) => {
+ Some(TermOrderCategory::Atom)
+ }
+ HeapCellValue::Integer(_) => {
+ Some(TermOrderCategory::Integer)
+ }
+ HeapCellValue::Rational(_) => {
+ Some(TermOrderCategory::Integer)
+ }
+ HeapCellValue::DBRef(_) => {
+ None
+ }
+ _ => {
+ unreachable!()
+ }
+ }
+ }
+ Addr::Char(_) | Addr::CharCode(_) | Addr::EmptyList => {
+ Some(TermOrderCategory::Atom)
+ }
+ Addr::Lis(_) | Addr::PStrLocation(..) | Addr::Str(_) => {
+ Some(TermOrderCategory::Compound)
+ }
+ Addr::CutPoint(_) | Addr::Usize(_) | Addr::Stream(_) => {
+ None
+ }
+ }
+ }
+
+ pub fn as_constant(&self, machine_st: &MachineState) -> Option<Constant> {
+ match self {
+ &Addr::Char(c) => {
+ Some(Constant::Char(c))
+ }
+ &Addr::CharCode(c) => {
+ Some(Constant::CharCode(c))
+ }
+ &Addr::Con(h) => {
+ match &machine_st.heap[h] {
+ &HeapCellValue::Atom(ref name, ref op) => {
+ Some(Constant::Atom(name.clone(), op.clone()))
+ }
+ &HeapCellValue::Integer(ref n) => {
+ Some(Constant::Integer(n.clone()))
+ }
+ &HeapCellValue::Rational(ref n) => {
+ Some(Constant::Rational(n.clone()))
+ }
+ _ => {
+ None
+ }
+ }
+ }
+ &Addr::Float(f) => {
+ Some(Constant::Float(f))
+ }
+ &Addr::PStrLocation(h, n) => {
+ machine_st.to_complete_string(h, n)
+ .map(|s| Constant::String(Rc::new(s)))
+ }
+ _ => {
+ None
+ }
+ }
+ }
+
pub fn is_protected(&self, e: usize) -> bool {
match self {
&Addr::StackCell(addr, _) if addr >= e => false,
}
}
-#[derive(Clone, PartialEq)]
pub enum HeapCellValue {
Addr(Addr),
+ Atom(ClauseName, Option<SharedOpDesc>),
+ DBRef(DBRef),
+ Integer(Rc<Integer>),
NamedStr(usize, ClauseName, Option<SharedOpDesc>), // arity, name, precedence/Specifier if it has one.
+ Rational(Rc<Rational>),
PartialString(PartialString),
+ Stream(Stream),
}
impl HeapCellValue {
+ #[inline]
pub fn as_addr(&self, focus: usize) -> Addr {
match self {
HeapCellValue::Addr(ref a) => {
a.clone()
}
+ HeapCellValue::Atom(..) | HeapCellValue::DBRef(..) | HeapCellValue::Integer(..) |
+ HeapCellValue::Rational(..) => {
+ Addr::Con(focus)
+ }
HeapCellValue::NamedStr(_, _, _) => {
Addr::Str(focus)
}
HeapCellValue::PartialString(_) => {
Addr::PStrLocation(focus, 0)
}
+ HeapCellValue::Stream(_) => {
+ Addr::Stream(focus)
+ }
+ }
+ }
+
+ #[inline]
+ pub fn context_free_clone(&self) -> HeapCellValue {
+ match self {
+ &HeapCellValue::Addr(addr) => {
+ HeapCellValue::Addr(addr)
+ }
+ &HeapCellValue::Atom(ref name, ref op) => {
+ HeapCellValue::Atom(name.clone(), op.clone())
+ }
+ &HeapCellValue::DBRef(ref db_ref) => {
+ HeapCellValue::DBRef(db_ref.clone())
+ }
+ &HeapCellValue::Integer(ref n) => {
+ HeapCellValue::Integer(n.clone())
+ }
+ &HeapCellValue::NamedStr(arity, ref name, ref op) => {
+ HeapCellValue::NamedStr(arity, name.clone(), op.clone())
+ }
+ &HeapCellValue::Rational(ref r) => {
+ HeapCellValue::Rational(r.clone())
+ }
+ &HeapCellValue::PartialString(ref pstr) => {
+ HeapCellValue::PartialString(pstr.clone())
+ }
+ &HeapCellValue::Stream(_) => {
+ HeapCellValue::Stream(Stream::null_stream())
+ }
}
}
}
+impl From<Addr> for HeapCellValue {
+ #[inline]
+ fn from(value: Addr) -> HeapCellValue {
+ HeapCellValue::Addr(value)
+ }
+}
+
#[derive(Clone, Copy, Eq, PartialEq, Ord, PartialOrd)]
pub enum IndexPtr {
DynamicUndefined, // a predicate, declared as dynamic, whose location in code is as yet undefined.
LocalCodePtr::DirEntry(p) => {
heap.append(functor!(
"dir_entry",
- 1,
- [heap_integer!(Integer::from(*p))]
+ [integer(*p)]
));
}
LocalCodePtr::InSituDirEntry(p) => {
heap.append(functor!(
"in_situ_dir_entry",
- 1,
- [heap_integer!(Integer::from(*p))]
+ [integer(*p)]
));
}
LocalCodePtr::TopLevel(chunk_num, offset) => {
heap.append(functor!(
"top_level",
- 2,
- [heap_integer!(Integer::from(*chunk_num)),
- heap_integer!(Integer::from(*offset))]
+ [integer(*chunk_num), integer(*offset)]
));
}
LocalCodePtr::UserGoalExpansion(p) => {
heap.append(functor!(
"user_goal_expansion",
- 1,
- [heap_integer!(Integer::from(*p))]
+ [integer(*p)]
));
}
LocalCodePtr::UserTermExpansion(p) => {
heap.append(functor!(
"user_term_expansion",
- 1,
- [heap_integer!(Integer::from(*p))]
+ [integer(*p)]
));
}
}
impl PartialOrd<CodePtr> for CodePtr {
fn partial_cmp(&self, other: &CodePtr) -> Option<Ordering> {
match (self, other) {
- (&CodePtr::Local(ref l1), &CodePtr::Local(ref l2)) => l1.partial_cmp(l2),
- _ => Some(Ordering::Greater),
+ (&CodePtr::Local(ref l1), &CodePtr::Local(ref l2)) => {
+ l1.partial_cmp(l2)
+ }
+ _ => {
+ Some(Ordering::Greater)
+ }
}
}
}
| (&LocalCodePtr::TopLevel(_, p1), &LocalCodePtr::TopLevel(_, ref p2)) => {
p1.partial_cmp(p2)
}
- (_, &LocalCodePtr::TopLevel(_, _)) => Some(Ordering::Less),
- _ => Some(Ordering::Greater),
+ (_, &LocalCodePtr::TopLevel(_, _)) => {
+ Some(Ordering::Less)
+ }
+ _ => {
+ Some(Ordering::Greater)
+ }
}
}
}
use std::io::Write;
use std::mem;
use std::ops::{Index, IndexMut};
-use std::rc::Rc;
pub struct Ball {
pub(super) boundary: usize,
for heap_value in self.stub.iter_from(0) {
stub.push(match heap_value {
- HeapCellValue::Addr(ref addr) => {
- HeapCellValue::Addr(addr.clone() - diff)
+ &HeapCellValue::Addr(addr) => {
+ HeapCellValue::Addr(addr - diff)
}
heap_value => {
- heap_value.clone()
+ heap_value.context_free_clone()
}
});
}
let index = h - self.heap_boundary;
self.stub[index].as_addr(h)
}
- Addr::StackCell(fr, sc) => self.stack.index_and_frame(fr)[sc].clone(),
- addr => addr,
+ Addr::StackCell(fr, sc) => {
+ self.stack.index_and_frame(fr)[sc].clone()
+ }
+ addr => {
+ addr
+ }
}
}
HeapCell(usize),
PStrChar(usize, usize),
PStrLocation(usize, usize),
- StringChar(usize, Rc<String>),
- StringLocation(usize, Rc<String>),
}
impl HeapPtr {
pub(super)
fn read(&self, heap: &Heap) -> Addr {
match self {
- &HeapPtr::HeapCell(h) =>
- Addr::HeapCell(h),
- &HeapPtr::PStrChar(h, n) =>
+ &HeapPtr::HeapCell(h) => {
+ Addr::HeapCell(h)
+ }
+ &HeapPtr::PStrChar(h, n) => {
if let HeapCellValue::PartialString(ref pstr) = &heap[h] {
- let s = pstr.block_as_str();
-
- if let Some(c) = s[n ..].chars().next() {
- Addr::Con(Constant::Char(c))
+ if let Some(c) = pstr.range_from(n ..).next() {
+ Addr::Char(c)
} else {
Addr::HeapCell(h + 1)
}
} else {
unreachable!()
- },
- &HeapPtr::PStrLocation(h, n) =>
- Addr::PStrLocation(h, n),
- &HeapPtr::StringChar(n, ref s) =>
- if let Some(c) = s[n ..].chars().next() {
- Addr::Con(Constant::Char(c))
- } else {
- Addr::Con(Constant::EmptyList)
- },
- &HeapPtr::StringLocation(n, ref s) =>
- Addr::Con(Constant::String(n, s.clone())),
+ }
+ }
+ &HeapPtr::PStrLocation(h, n) => {
+ Addr::PStrLocation(h, n)
+ }
}
}
}
let addr = self.store(self.deref(addr.clone()));
match addr {
- Addr::Con(Constant::String(n, ref s))
- if self.flags.double_quotes.is_chars() => {
- if s.len() < n {
- chars += &s[n ..];
- }
-
- if iter.next().is_some() {
- return Err(MachineError::type_error(ValidType::Character, addr.clone()));
- }
- }
- Addr::Con(Constant::Char(c)) => {
+ Addr::Char(c) => {
chars.push(c);
+ continue;
}
- Addr::Con(Constant::Atom(ref name, _))
- if name.as_str().len() == 1 => {
- chars += name.as_str();
+ Addr::Con(h) => {
+ if let HeapCellValue::Atom(ref name, _) = &self.heap[h] {
+ if name.is_char() {
+ chars += name.as_str();
+ continue;
+ }
}
+ }
_ => {
- return Err(
- MachineError::type_error(ValidType::Character, addr.clone())
- );
}
- }
+ };
+
+ let h = self.heap.h();
+
+ return Err(
+ MachineError::type_error(h, ValidType::Character, addr)
+ );
}
Ok(chars)
let a2 = machine_st[temp_v!(2)].clone();
let a3 = machine_st[temp_v!(3)].clone();
- let c = match machine_st.compare_term_test(&a2, &a3) {
- Ordering::Greater => {
+ let atom = match machine_st.compare_term_test(&a2, &a3) {
+ Some(Ordering::Greater) => {
let spec = fetch_atom_op_spec(clause_name!(">"), None, &indices.op_dir);
- Addr::Con(Constant::Atom(clause_name!(">"), spec))
+ HeapCellValue::Atom(clause_name!(">"), spec)
}
- Ordering::Equal => {
+ Some(Ordering::Equal) => {
let spec = fetch_atom_op_spec(clause_name!("="), None, &indices.op_dir);
- Addr::Con(Constant::Atom(clause_name!("="), spec))
+ HeapCellValue::Atom(clause_name!("="), spec)
}
- Ordering::Less => {
+ None | Some(Ordering::Less) => {
let spec = fetch_atom_op_spec(clause_name!("<"), None, &indices.op_dir);
- Addr::Con(Constant::Atom(clause_name!("<"), spec))
+ HeapCellValue::Atom(clause_name!("<"), spec)
}
};
- machine_st.unify(a1, c);
+ let h = machine_st.heap.h();
+
+ machine_st.heap.push(atom);
+ machine_st.unify(a1, Addr::Con(h));
+
return_from_clause!(machine_st.last_call, machine_st)
}
&BuiltInClauseType::CompareTerm(qt) => {
machine_st.compare_term(qt);
return_from_clause!(machine_st.last_call, machine_st)
}
- &BuiltInClauseType::Nl => {
+ &BuiltInClauseType::Nl => {
write!(current_output_stream, "\n").unwrap();
current_output_stream.flush().unwrap();
-
+
return_from_clause!(machine_st.last_call, machine_st)
}
&BuiltInClauseType::Read => {
let a1 = machine_st[temp_v!(1)].clone();
let a2 = machine_st[temp_v!(2)].clone();
- machine_st.fail = if let Ordering::Equal = machine_st.compare_term_test(&a1, &a2) {
- true
- } else {
- false
- };
+ machine_st.fail =
+ if let Some(Ordering::Equal) = machine_st.compare_term_test(&a1, &a2) {
+ true
+ } else {
+ false
+ };
return_from_clause!(machine_st.last_call, machine_st)
}
let stub = MachineError::functor_stub(clause_name!("sort"), 2);
let mut list = machine_st.try_from_list(temp_v!(1), stub)?;
- list.sort_unstable_by(|a1, a2| machine_st.compare_term_test(a1, a2));
+ list.sort_unstable_by(|a1, a2| {
+ machine_st.compare_term_test(a1, a2).unwrap_or(Ordering::Less)
+ });
+
machine_st.term_dedup(&mut list);
let heap_addr = Addr::HeapCell(machine_st.heap.to_list(list.into_iter()));
key_pairs.push((key, val.clone()));
}
- key_pairs.sort_by(|a1, a2| machine_st.compare_term_test(&a1.0, &a2.0));
+ key_pairs.sort_by(|a1, a2| {
+ machine_st.compare_term_test(&a1.0, &a2.0).unwrap_or(Ordering::Less)
+ });
let key_pairs = key_pairs.into_iter().map(|kp| kp.1);
let heap_addr = Addr::HeapCell(machine_st.heap.to_list(key_pairs));
}
&BuiltInClauseType::Is(r, ref at) => {
let a1 = machine_st[r].clone();
- let a2 = machine_st.get_number(at)?;
+ let n2 = machine_st.get_number(at)?;
+
+ let n2 = Addr::Con(machine_st.heap.push(n2.into()));
+ machine_st.unify(a1, n2);
- machine_st.unify(a1, Addr::Con(a2.to_constant()));
return_from_clause!(machine_st.last_call, machine_st)
}
}
}
}
ClauseType::Hook(_) | ClauseType::System(_) => {
- let name = Addr::Con(Constant::Atom(name, None));
+ let name = functor!(clause_name(name));
let stub = MachineError::functor_stub(clause_name!("call"), arity + 1);
- return Err(machine_st
- .error_form(MachineError::type_error(ValidType::Callable, name), stub));
+ return Err(machine_st.error_form(
+ MachineError::type_error(machine_st.heap.h(), ValidType::Callable, name),
+ stub,
+ ));
}
};
}
current_input_stream,
current_output_stream
)?;
-
+
self.increment(machine_st)
}
current_input_stream,
current_output_stream,
)?;
-
+
self.increment(machine_st)
}
}
}
impl CWILCallPolicy {
- pub(crate) fn new_in_place(policy: &mut Box<dyn CallPolicy>) {
+ pub(crate)
+ fn new_in_place(policy: &mut Box<dyn CallPolicy>) {
let mut prev_policy: Box<dyn CallPolicy> = Box::new(DefaultCallPolicy {});
mem::swap(&mut prev_policy, policy);
limits: vec![],
inference_limit_exceeded: false,
};
+
*policy = Box::new(new_policy);
}
if let Some(&(ref limit, bp)) = self.limits.last() {
if self.count == *limit {
self.inference_limit_exceeded = true;
+
return Err(functor!(
"inference_limit_exceeded",
- 1,
- [HeapCellValue::Addr(Addr::Con(Constant::Usize(bp)))]
+ [addr(Addr::Usize(bp))]
));
} else {
self.count += 1;
Ok(())
}
- pub(crate) fn add_limit(&mut self, mut limit: Integer, b: usize) -> &Integer {
+ pub(crate)
+ fn add_limit(&mut self, mut limit: Integer, b: usize) -> &Integer {
limit += &self.count;
match self.limits.last().cloned() {
&self.count
}
- pub(crate) fn remove_limit(&mut self, b: usize) -> &Integer {
+ pub(crate)
+ fn remove_limit(&mut self, b: usize) -> &Integer {
if let Some((_, bp)) = self.limits.last().cloned() {
if bp == b {
self.limits.pop();
&self.count
}
- pub(crate) fn is_empty(&self) -> bool {
+ pub(crate)
+ fn is_empty(&self) -> bool {
self.limits.is_empty()
}
- pub(crate) fn into_inner(&mut self) -> Box<dyn CallPolicy> {
+ pub(crate)
+ fn into_inner(&mut self) -> Box<dyn CallPolicy> {
let mut new_inner: Box<dyn CallPolicy> = Box::new(DefaultCallPolicy {});
mem::swap(&mut self.prev_policy, &mut new_inner);
new_inner
downcast!(dyn CutPolicy);
-fn cut_body(machine_st: &mut MachineState, addr: Addr) -> bool {
+fn cut_body(machine_st: &mut MachineState, addr: &Addr) -> bool {
let b = machine_st.b;
match addr {
- Addr::Con(Constant::CutPoint(b0)) | Addr::Con(Constant::Usize(b0)) => {
+ &Addr::CutPoint(b0) | &Addr::Usize(b0) => {
if b > b0 {
machine_st.b = b0;
machine_st.tidy_trail();
pub(super) fn deref_cut(machine_st: &mut MachineState, r: RegType) {
let addr = machine_st.store(machine_st.deref(machine_st[r].clone()));
- cut_body(machine_st, addr);
+ cut_body(machine_st, &addr);
}
impl CutPolicy for DefaultCutPolicy {
fn cut(&mut self, machine_st: &mut MachineState, r: RegType) -> bool {
let addr = machine_st[r].clone();
- cut_body(machine_st, addr)
+ cut_body(machine_st, &addr)
}
}
let (idx, arity) = if machine_st.block < prev_block {
(dir_entry!(self.r_c_w_h), 0)
} else {
- machine_st[temp_v!(1)] = Addr::Con(Constant::Usize(b_cutoff));
+ machine_st[temp_v!(1)] = Addr::Usize(b_cutoff);
(dir_entry!(self.r_c_wo_h), 1)
};
let b = machine_st.b;
match machine_st[r].clone() {
- Addr::Con(Constant::Usize(b0)) | Addr::Con(Constant::CutPoint(b0)) => {
+ Addr::Usize(b0) | Addr::CutPoint(b0) => {
if b > b0 {
machine_st.b = b0;
machine_st.tidy_trail();
use prolog_parser::ast::*;
use prolog_parser::tabled_rc::*;
-use crate::prolog::arithmetic::*;
use crate::prolog::clause_types::*;
use crate::prolog::forms::*;
use crate::prolog::heap_iter::*;
use crate::prolog::machine::stack::*;
use crate::prolog::machine::streams::*;
use crate::prolog::ordered_float::*;
-use crate::prolog::rug::{Integer, Rational};
+use crate::prolog::rug::Integer;
use indexmap::{IndexMap, IndexSet};
-use std::cmp::{max, min, Ordering};
-use std::f64;
-use std::iter::FromIterator;
-use std::mem;
+use std::cmp::Ordering;
use std::rc::Rc;
-macro_rules! try_numeric_result {
- ($s: ident, $e: expr, $caller: expr) => {{
- match $e {
- Ok(val) => Ok(val),
- Err(e) => Err($s.error_form(MachineError::evaluation_error(e), $caller)),
- }
- }};
-}
-
macro_rules! try_or_fail {
($s:ident, $e:expr) => {{
match $e {
}
Addr::PStrLocation(h, n) => {
if let HeapCellValue::PartialString(ref pstr) = &self.heap[h] {
- if pstr.len() > n {
+ if !pstr.at_end(n) {
Addr::PStrLocation(h, n)
} else {
Addr::HeapCell(h + 1)
}
}
- fn deconstruct_chars(
- &mut self,
- s: Rc<String>,
- string_offset: usize,
- list_cell: usize,
- pdl: &mut Vec<Addr>,
- ) -> bool {
- if s.len() > string_offset {
- if let Some(c) = s[string_offset ..].chars().next() {
- pdl.push(Addr::Con(Constant::String(string_offset + c.len_utf8(), s)));
- pdl.push(Addr::HeapCell(list_cell + 1));
-
- pdl.push(Addr::Con(Constant::Char(c)));
- pdl.push(Addr::HeapCell(list_cell));
-
- return true;
- }
- }
-
- false
- }
-
fn bind_with_occurs_check(&mut self, r: Ref, addr: Addr) {
let mut fail = false;
- for value in self.acyclic_pre_order_iter(addr.clone()) {
- if let HeapCellValue::Addr(addr) = value {
- if let Some(inner_r) = addr.as_var() {
- if r == inner_r {
- fail = true;
- break;
- }
+ for addr in self.acyclic_pre_order_iter(addr) {
+ if let Some(inner_r) = addr.as_var() {
+ if r == inner_r {
+ fail = true;
+ break;
}
}
}
self.fail = true;
}
- (Addr::Lis(a1), Addr::Con(Constant::String(n, s)))
- | (Addr::Con(Constant::String(n, s)), Addr::Lis(a1))
- if !self.flags.double_quotes.is_atom() =>
- {
- if self.deconstruct_chars(s, n, a1, &mut pdl) {
- continue;
- }
-
- self.fail = true;
- }
- (Addr::Con(Constant::EmptyList), Addr::Con(Constant::String(n, ref s)))
- | (Addr::Con(Constant::String(n, ref s)), Addr::Con(Constant::EmptyList))
- if !self.flags.double_quotes.is_atom() =>
- {
- if n >= s.len() {
- continue;
- }
-
- self.fail = true;
- }
(Addr::PStrLocation(h, n), Addr::Lis(l))
| (Addr::Lis(l), Addr::PStrLocation(h, n)) => {
if let HeapCellValue::PartialString(ref pstr) = &self.heap[h] {
- let s = pstr.block_as_str();
-
- if let Some(c) = s[n ..].chars().next() {
+ if let Some(c) = pstr.range_from(n ..).next() {
pdl.push(Addr::PStrLocation(h, n + c.len_utf8()));
pdl.push(Addr::HeapCell(l + 1));
- pdl.push(Addr::Con(Constant::Char(c)));
+ pdl.push(Addr::Char(c));
pdl.push(Addr::HeapCell(l));
+ } else {
+ unreachable!()
}
+ } else {
+ unreachable!()
}
}
- (Addr::PStrLocation(h, n), Addr::Con(Constant::String(n1, s)))
- | (Addr::Con(Constant::String(n1, s)), Addr::PStrLocation(h, n))
- if self.flags.double_quotes.is_chars() => {
- if let HeapCellValue::PartialString(ref pstr) = &self.heap[h] {
- let pstr_s = pstr.block_as_str();
-
- let pstr_len = pstr_s[n ..].len();
- let s_len = s[n1 ..].len();
- let m_len = std::cmp::min(s_len, pstr_len);
-
- if pstr_s[n .. n + m_len] == s[n1 .. n1 + m_len] {
- if s_len <= pstr_len {
- pdl.push(Addr::Con(Constant::EmptyList));
- pdl.push(Addr::PStrLocation(h, n + m_len));
- } else {
- pdl.push(Addr::Con(Constant::String(n1 + m_len, s)));
- pdl.push(Addr::HeapCell(h + 1));
- }
-
- continue;
- }
-
- self.fail = true;
- break;
- }
- }
(Addr::PStrLocation(h1, n1), Addr::PStrLocation(h2, n2)) => {
if let HeapCellValue::PartialString(ref pstr1) = &self.heap[h1] {
if let HeapCellValue::PartialString(ref pstr2) = &self.heap[h2] {
- let pstr_s1 = pstr1.block_as_str();
- let pstr_s2 = pstr2.block_as_str();
+ let pstr1_iter = pstr1.range_from(n1 ..);
+ let pstr2_iter = pstr2.range_from(n2 ..);
- let pstr_s1_len = pstr_s1[n1 ..].len();
- let pstr_s2_len = pstr_s2[n2 ..].len();
- let m_len = std::cmp::min(pstr_s1_len, pstr_s2_len);
+ let mut m_len = 0;
- if pstr_s1[n1 .. n1 + m_len] == pstr_s2[n2 .. n2 + m_len] {
- if pstr_s1_len <= pstr_s2_len {
- pdl.push(Addr::HeapCell(h1 + 1));
- pdl.push(Addr::PStrLocation(h2, n2 + m_len));
- } else {
- pdl.push(Addr::HeapCell(h2 + 1));
- pdl.push(Addr::PStrLocation(h1, n1 + m_len));
+ for (c1, c2) in pstr1_iter.zip(pstr2_iter) {
+ if c1 != c2 {
+ self.fail = true;
+ return;
}
- continue;
+ m_len += 1;
+ }
+
+ if pstr1.at_end(n1 + m_len) {
+ pdl.push(Addr::HeapCell(h1 + 1));
+ pdl.push(Addr::PStrLocation(h2, n2 + m_len));
+ } else {
+ pdl.push(Addr::HeapCell(h2 + 1));
+ pdl.push(Addr::PStrLocation(h1, n1 + m_len));
}
self.fail = true;
break;
+ } else {
+ unreachable!()
}
+ } else {
+ unreachable!()
}
}
(Addr::Lis(a1), Addr::Lis(a2)) => {
pdl.push(Addr::HeapCell(a1 + 1));
pdl.push(Addr::HeapCell(a2 + 1));
}
- (Addr::Con(ref c1), Addr::Con(ref c2)) => {
+ (Addr::Con(c1), Addr::Con(c2)) => {
if c1 != c2 {
self.fail = true;
}
self.fail = true;
}
- (Addr::Lis(a1), Addr::Con(Constant::String(n, s)))
- | (Addr::Con(Constant::String(n, s)), Addr::Lis(a1))
- if !self.flags.double_quotes.is_atom() => {
- if self.deconstruct_chars(s, n, a1, &mut pdl) {
- continue;
- }
-
- self.fail = true;
- }
- (Addr::Con(Constant::EmptyList), Addr::Con(Constant::String(n, ref s)))
- | (Addr::Con(Constant::String(n, ref s)), Addr::Con(Constant::EmptyList))
- if !self.flags.double_quotes.is_atom() =>
- {
- if n >= s.len() {
- continue;
- }
-
- self.fail = true;
- }
(Addr::PStrLocation(h, n), Addr::Lis(l))
| (Addr::Lis(l), Addr::PStrLocation(h, n)) => {
- if let HeapCellValue::PartialString(ref pstr) = &self.heap[h] {
- let s = pstr.block_as_str();
-
- if let Some(c) = s[n ..].chars().next() {
- pdl.push(Addr::PStrLocation(h, n + c.len_utf8()));
- pdl.push(Addr::HeapCell(l + 1));
-
- pdl.push(Addr::Con(Constant::Char(c)));
- pdl.push(Addr::HeapCell(l));
- }
- }
+ 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()));
+ pdl.push(Addr::HeapCell(l + 1));
+
+ pdl.push(Addr::Char(c));
+ pdl.push(Addr::HeapCell(l));
+ } else {
+ unreachable!()
+ }
+ } else {
+ unreachable!()
+ }
}
- (Addr::PStrLocation(h, n), Addr::Con(Constant::String(n1, s)))
- | (Addr::Con(Constant::String(n1, s)), Addr::PStrLocation(h, n))
- if self.flags.double_quotes.is_chars() => {
- if let HeapCellValue::PartialString(ref pstr) = &self.heap[h] {
- let pstr_s = pstr.block_as_str();
-
- let pstr_len = pstr_s[n ..].len();
- let s_len = s[n1 ..].len();
- let m_len = std::cmp::min(s_len, pstr_len);
-
- if pstr_s[n .. n + m_len] == s[n1 .. n1 + m_len] {
- if s_len <= pstr_len {
- pdl.push(Addr::Con(Constant::EmptyList));
- pdl.push(Addr::PStrLocation(h, n + m_len));
- } else {
- pdl.push(Addr::Con(Constant::String(n1 + m_len, s)));
- pdl.push(Addr::HeapCell(h + 1));
- }
-
- continue;
- }
-
- self.fail = true;
- break;
- }
- }
(Addr::PStrLocation(h1, n1), Addr::PStrLocation(h2, n2)) => {
if let HeapCellValue::PartialString(ref pstr1) = &self.heap[h1] {
if let HeapCellValue::PartialString(ref pstr2) = &self.heap[h2] {
- let pstr_s1 = pstr1.block_as_str();
- let pstr_s2 = pstr2.block_as_str();
+ let pstr1_iter = pstr1.range_from(n1 ..);
+ let pstr2_iter = pstr2.range_from(n2 ..);
- let pstr_s1_len = pstr_s1[n1 ..].len();
- let pstr_s2_len = pstr_s2[n2 ..].len();
- let m_len = std::cmp::min(pstr_s1_len, pstr_s2_len);
+ let mut m_len = 0;
- if pstr_s1[n1 .. n1 + m_len] == pstr_s2[n2 .. n2 + m_len] {
- if pstr_s1_len <= pstr_s2_len {
- pdl.push(Addr::HeapCell(h1 + 1));
- pdl.push(Addr::PStrLocation(h2, n2 + m_len));
- } else {
- pdl.push(Addr::HeapCell(h2 + 1));
- pdl.push(Addr::PStrLocation(h1, n1 + m_len));
+ for (c1, c2) in pstr1_iter.zip(pstr2_iter) {
+ if c1 != c2 {
+ self.fail = true;
+ return;
}
- continue;
+ m_len += 1;
+ }
+
+ if pstr1.at_end(n1 + m_len) {
+ pdl.push(Addr::HeapCell(h1 + 1));
+ pdl.push(Addr::PStrLocation(h2, n2 + m_len));
+ } else {
+ pdl.push(Addr::HeapCell(h2 + 1));
+ pdl.push(Addr::PStrLocation(h1, n1 + m_len));
}
self.fail = true;
pdl.push(Addr::HeapCell(a1 + 1));
pdl.push(Addr::HeapCell(a2 + 1));
}
- (Addr::Con(ref c1), Addr::Con(ref c2)) => {
+ (Addr::Con(c1), Addr::Con(c2)) => {
if c1 != c2 {
self.fail = true;
}
}
}
+ pub(super)
+ fn to_complete_string(&self, h: usize, n: usize) -> Option<String> {
+ if self.is_cyclic_term(Addr::PStrLocation(h, n)) {
+ return None;
+ }
+
+ let mut addr = Addr::PStrLocation(h, n);
+ let mut result = String::new();
+
+ loop {
+ match addr {
+ Addr::EmptyList => {
+ break;
+ }
+ Addr::Lis(l) if !self.flags.double_quotes.is_atom() => {
+ if let &HeapCellValue::Addr(Addr::Char(c)) = &self.heap[l] {
+ result.push(c);
+ addr = self.store(self.deref(Addr::HeapCell(l + 1)));
+ } else {
+ return None;
+ }
+ }
+ Addr::PStrLocation(h, n) => {
+ if let HeapCellValue::PartialString(ref pstr) = &self.heap[h] {
+ result.extend(pstr.range_from(n ..));
+ addr = self.store(self.deref(Addr::HeapCell(h + 1)));
+ } else {
+ unreachable!()
+ }
+ }
+ _ => {
+ return None;
+ }
+ }
+ }
+
+ Some(result)
+ }
+
pub(super)
fn trail(&mut self, r: TrailRef) {
match r {
HeapPtr::HeapCell(ref mut h) => {
*h += rhs;
}
- HeapPtr::PStrChar(h, n) | HeapPtr::PStrLocation(h, n) => {
- match &self.heap[*h] {
+ &mut HeapPtr::PStrChar(h, ref mut n)
+ | &mut HeapPtr::PStrLocation(h, ref mut n) => {
+ match &self.heap[h] {
HeapCellValue::PartialString(ref pstr) => {
- let s = pstr.block_as_str();
-
- for c in s[*n ..].chars().take(rhs) {
+ for c in pstr.range_from(*n ..).take(rhs) {
*n += c.len_utf8();
}
- self.s = HeapPtr::PStrLocation(*h, *n);
+ self.s = HeapPtr::PStrLocation(h, *n);
}
_ => {
unreachable!()
}
}
}
- HeapPtr::StringChar(n, s) | HeapPtr::StringLocation(n, s) => {
- for c in s[*n ..].chars().take(rhs) {
- *n += c.len_utf8();
- }
-
- self.s = HeapPtr::StringLocation(*n, s.clone());
- }
}
}
self.trail.truncate(self.tr);
}
- pub(super) fn write_constant_to_var(&mut self, addr: Addr, c: Constant) {
+ pub(super)
+ fn write_constant_to_var(&mut self, addr: Addr, c: &Constant) {
match self.store(self.deref(addr)) {
- Addr::Con(c1) =>
- self.fail = self.eq_test(Addr::Con(c), Addr::Con(c1)),
- Addr::Lis(l) =>
- self.unify(Addr::Lis(l), Addr::Con(c)),
- addr => {
- if let Some(r) = addr.as_var() {
- self.bind(r, Addr::Con(c));
+ Addr::Con(c1) => {
+ self.fail = match &self.heap[c1] {
+ HeapCellValue::Atom(ref n1, ref op1) => {
+ if let Constant::Atom(ref n2, ref op2) = c {
+ !(n1 == n2 && op1 == op2)
+ } else {
+ true
+ }
+ }
+ HeapCellValue::Integer(ref n1) => {
+ if let Constant::Integer(ref n2) = c {
+ n1 != n2
+ } else {
+ true
+ }
+ }
+ HeapCellValue::Rational(ref r1) => {
+ if let Constant::Rational(ref r2) = c {
+ r1 != r2
+ } else {
+ true
+ }
+ }
+ HeapCellValue::PartialString(_) => {
+ self.to_complete_string(c1, 0).map(|s1| {
+ if let Constant::String(ref s2) = c {
+ &s1 != &**s2
+ } else {
+ true
+ }
+ }).unwrap_or(true)
+ }
+ _ => {
+ unreachable!()
+ }
+ };
+ }
+ Addr::EmptyList => {
+ if let Constant::EmptyList = c {
} else {
self.fail = true;
}
}
- };
- }
-
- pub(super) fn get_number(&mut self, at: &ArithmeticTerm) -> Result<Number, MachineStub> {
- match at {
- &ArithmeticTerm::Reg(r) => self.arith_eval_by_metacall(r),
- &ArithmeticTerm::Interm(i) => Ok(mem::replace(
- &mut self.interms[i - 1],
- Number::Integer(Integer::from(0)),
- )),
- &ArithmeticTerm::Number(ref n) => Ok(n.clone()),
- }
- }
-
- fn rational_from_number(
- &self,
- n: Number,
- caller: &MachineStub,
- ) -> Result<Rational, MachineStub> {
- match n {
- Number::Rational(r) => Ok(r),
- Number::Float(OrderedFloat(f)) => Rational::from_f64(f).ok_or_else(|| {
- self.error_form(MachineError::instantiation_error(), caller.clone())
- }),
- Number::Integer(n) => Ok(Rational::from(n)),
- }
- }
-
- fn get_rational(
- &mut self,
- at: &ArithmeticTerm,
- caller: &MachineStub,
- ) -> Result<Rational, MachineStub> {
- let n = self.get_number(at)?;
- self.rational_from_number(n, caller)
- }
-
- pub(super) fn arith_eval_by_metacall(&self, r: RegType) -> Result<Number, MachineStub> {
- let a = self[r].clone();
-
- let caller = MachineError::functor_stub(clause_name!("(is)"), 2);
- let mut interms: Vec<Number> = Vec::with_capacity(64);
-
- for heap_val in self.post_order_iter(a) {
- match heap_val {
- HeapCellValue::NamedStr(2, name, _) => {
- let a2 = interms.pop().unwrap();
- let a1 = interms.pop().unwrap();
-
- match name.as_str() {
- "+" => interms.push(try_numeric_result!(self, a1 + a2, caller.clone())?),
- "-" => interms.push(try_numeric_result!(self, a1 - a2, caller.clone())?),
- "*" => interms.push(try_numeric_result!(self, a1 * a2, caller.clone())?),
- "/" => interms.push(self.div(a1, a2)?),
- "**" => interms.push(self.pow(a1, a2, "(is)")?),
- "^" => interms.push(self.int_pow(a1, a2)?),
- "max" => interms.push(self.max(a1, a2)?),
- "min" => interms.push(self.min(a1, a2)?),
- "rdiv" => {
- let r1 = self.rational_from_number(a1, &caller)?;
- let r2 = self.rational_from_number(a2, &caller)?;
-
- let result = Number::Rational(self.rdiv(r1, r2)?);
- interms.push(result)
- }
- "//" => interms.push(Number::Integer(self.idiv(a1, a2)?)),
- "div" => interms.push(Number::Integer(self.int_floor_div(a1, a2)?)),
- ">>" => interms.push(Number::Integer(self.shr(a1, a2)?)),
- "<<" => interms.push(Number::Integer(self.shl(a1, a2)?)),
- "/\\" => interms.push(Number::Integer(self.and(a1, a2)?)),
- "\\/" => interms.push(Number::Integer(self.or(a1, a2)?)),
- "xor" => interms.push(Number::Integer(self.xor(a1, a2)?)),
- "mod" => interms.push(Number::Integer(self.modulus(a1, a2)?)),
- "rem" => interms.push(Number::Integer(self.remainder(a1, a2)?)),
- "atan2" => interms.push(Number::Float(OrderedFloat(self.atan2(a1, a2)?))),
- "gcd" => interms.push(Number::Integer(self.gcd(a1, a2)?)),
- _ => {
- return Err(self.error_form(MachineError::instantiation_error(), caller))
- }
- }
- }
- HeapCellValue::NamedStr(1, name, _) => {
- let a1 = interms.pop().unwrap();
-
- match name.as_str() {
- "-" => interms.push(-a1),
- "+" => interms.push(a1),
- "cos" => interms.push(Number::Float(OrderedFloat(self.cos(a1)?))),
- "sin" => interms.push(Number::Float(OrderedFloat(self.sin(a1)?))),
- "tan" => interms.push(Number::Float(OrderedFloat(self.tan(a1)?))),
- "sqrt" => interms.push(Number::Float(OrderedFloat(self.sqrt(a1)?))),
- "log" => interms.push(Number::Float(OrderedFloat(self.log(a1)?))),
- "exp" => interms.push(Number::Float(OrderedFloat(self.exp(a1)?))),
- "acos" => interms.push(Number::Float(OrderedFloat(self.acos(a1)?))),
- "asin" => interms.push(Number::Float(OrderedFloat(self.asin(a1)?))),
- "atan" => interms.push(Number::Float(OrderedFloat(self.atan(a1)?))),
- "abs" => interms.push(a1.abs()),
- "float" => interms.push(Number::Float(OrderedFloat(self.float(a1)?))),
- "truncate" => interms.push(Number::Integer(self.truncate(a1))),
- "round" => interms.push(Number::Integer(self.round(a1)?)),
- "ceiling" => interms.push(Number::Integer(self.ceiling(a1))),
- "floor" => interms.push(Number::Integer(self.floor(a1))),
- "\\" => interms.push(Number::Integer(self.bitwise_complement(a1)?)),
- "sign" => interms.push(Number::Integer(self.sign(a1))),
- _ => {
- return Err(self.error_form(MachineError::instantiation_error(), caller))
- }
+ Addr::Lis(l) if !self.flags.double_quotes.is_atom() => {
+ let addr = self.heap.put_constant(c.clone());
+ self.unify(Addr::Lis(l), addr);
+ }
+ Addr::PStrLocation(h, n) => {
+ self.fail = self.to_complete_string(h, n).map(|s1| {
+ if let Constant::String(ref s2) = c {
+ &s1 != &**s2
+ } else {
+ true
}
- }
- HeapCellValue::Addr(Addr::Con(Constant::Integer(n))) => {
- interms.push(Number::Integer(n))
- }
- HeapCellValue::Addr(Addr::Con(Constant::Float(n))) => {
- interms.push(Number::Float(n))
- }
- HeapCellValue::Addr(Addr::Con(Constant::Rational(n))) => {
- interms.push(Number::Rational(n))
- }
- HeapCellValue::Addr(Addr::Con(Constant::Atom(ref name, _)))
- if name.as_str() == "pi" =>
- {
- interms.push(Number::Float(OrderedFloat(f64::consts::PI)))
- }
- _ => {
- return Err(self.error_form(MachineError::instantiation_error(), caller));
- }
+ }).unwrap_or(true);
}
- }
-
- Ok(interms.pop().unwrap())
- }
-
- fn rdiv(&self, r1: Rational, r2: Rational) -> Result<Rational, MachineStub> {
- let stub = MachineError::functor_stub(clause_name!("(rdiv)"), 2);
-
- if r2 == 0 {
- Err(self.error_form(MachineError::evaluation_error(EvalError::ZeroDivisor), stub))
- } else {
- Ok(r1 / r2)
- }
- }
-
- fn int_floor_div(&self, n1: Number, n2: Number) -> Result<Integer, MachineStub> {
- let stub = MachineError::functor_stub(clause_name!("(div)"), 2);
-
- match n1 / n2 {
- Ok(result) => Ok(rnd_i(&result).to_owned()),
- Err(e) => Err(self.error_form(MachineError::evaluation_error(e), stub)),
- }
- }
-
- fn idiv(&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)) => {
- if n2 == 0 {
- Err(self
- .error_form(MachineError::evaluation_error(EvalError::ZeroDivisor), stub))
+ addr => {
+ if let Some(r) = addr.as_var() {
+ let addr = self.heap.put_constant(c.clone());
+ self.bind(r, addr);
} else {
- Ok(n1.div_rem(n2).0)
+ self.fail = true;
}
}
- (Number::Integer(_), n2) => Err(self.error_form(
- MachineError::type_error(ValidType::Integer, Addr::Con(n2.to_constant())),
- stub,
- )),
- (n1, _) => Err(self.error_form(
- MachineError::type_error(ValidType::Integer, Addr::Con(n1.to_constant())),
- stub,
- )),
- }
- }
-
- fn div(&self, n1: Number, n2: Number) -> Result<Number, MachineStub> {
- let stub = MachineError::functor_stub(clause_name!("(/)"), 2);
-
- if n2.is_zero() {
- Err(self.error_form(MachineError::evaluation_error(EvalError::ZeroDivisor), stub))
- } else {
- try_numeric_result!(self, n1 / n2, stub)
- }
+ };
}
- fn atan2(&self, n1: Number, n2: Number) -> Result<f64, MachineStub> {
+ pub(super)
+ fn execute_arith_instr(&mut self, instr: &ArithmeticInstruction) {
let stub = MachineError::functor_stub(clause_name!("(is)"), 2);
- if n1.is_zero() && n2.is_zero() {
- Err(self.error_form(MachineError::evaluation_error(EvalError::Undefined), stub))
- } else {
- let f1 = self.float(n1)?;
- let f2 = self.float(n2)?;
-
- self.unary_float_fn_template(Number::Float(OrderedFloat(f1)), |f| f.atan2(f2))
- }
- }
-
- fn int_pow(&self, n1: Number, n2: Number) -> Result<Number, MachineStub> {
- if n1.is_zero() && n2.is_negative() {
- let stub = MachineError::functor_stub(clause_name!("(is)"), 2);
- return Err(self.error_form(MachineError::evaluation_error(EvalError::Undefined), stub));
- }
+ match instr {
+ &ArithmeticInstruction::Add(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));
- match (n1, n2) {
- (Number::Integer(n1), Number::Integer(n2)) => {
- if n1 != 1 && n2 < 0 {
- let n = Addr::Con(Constant::Integer(n1));
- let stub = MachineError::functor_stub(clause_name!("^"), 2);
+ self.interms[t - 1] = try_or_fail!(self, try_numeric_result!(self, n1 + n2, stub));
+ self.p += 1;
+ }
+ &ArithmeticInstruction::Sub(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));
- Err(self.error_form(MachineError::type_error(ValidType::Float, n), stub))
- } else {
- Ok(Number::Integer(binary_pow(n1, n2)))
- }
+ self.interms[t - 1] = try_or_fail!(self, try_numeric_result!(self, n1 - n2, stub));
+ self.p += 1;
}
- (n1, Number::Integer(n2)) => {
- let f1 = self.float(n1)?;
- let f2 = self.float(Number::Integer(n2))?;
+ &ArithmeticInstruction::Mul(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.unary_float_fn_template(Number::Float(OrderedFloat(f1)), |f| f.powf(f2))
- .map(|f| Number::Float(OrderedFloat(f)))
+ self.interms[t - 1] = try_or_fail!(self, try_numeric_result!(self, n1 * n2, stub));
+ self.p += 1;
}
- (n1, n2) => {
- let f2 = self.float(n2)?;
+ &ArithmeticInstruction::Max(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));
- if n1.is_negative() && f2 != f2.floor() {
- let stub = MachineError::functor_stub(clause_name!("(is)"), 2);
- return Err(
- self.error_form(MachineError::evaluation_error(EvalError::Undefined), stub)
- );
- }
+ self.interms[t - 1] = try_or_fail!(self, self.max(n1, n2));
+ self.p += 1;
+ }
+ &ArithmeticInstruction::Min(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));
- let f1 = self.float(n1)?;
- self.unary_float_fn_template(Number::Float(OrderedFloat(f1)), |f| f.powf(f2))
- .map(|f| Number::Float(OrderedFloat(f)))
+ self.interms[t - 1] = try_or_fail!(self, self.min(n1, n2));
+ self.p += 1;
}
- }
- }
+ &ArithmeticInstruction::IntPow(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));
- fn gcd(&self, n1: Number, n2: Number) -> Result<Integer, MachineStub> {
- match (n1, n2) {
- (Number::Integer(n1), Number::Integer(n2)) => {
- Ok(n1.gcd(&n2))
+ self.interms[t - 1] = try_or_fail!(self, self.int_pow(n1, n2));
+ self.p += 1;
}
- (Number::Float(f), _) | (_, Number::Float(f)) => {
- let n = Addr::Con(Constant::Float(f));
- let stub = MachineError::functor_stub(clause_name!("gcd"), 2);
+ &ArithmeticInstruction::Gcd(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));
- Err(self.error_form(MachineError::type_error(ValidType::Integer, n), stub))
+ self.interms[t - 1] =
+ Number::Integer(Rc::new(try_or_fail!(self, self.gcd(n1, n2))));
+ self.p += 1;
}
- (Number::Rational(r), _) | (_, Number::Rational(r)) => {
- let n = Addr::Con(Constant::Rational(r));
- let stub = MachineError::functor_stub(clause_name!("gcd"), 2);
+ &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));
- Err(self.error_form(MachineError::type_error(ValidType::Integer, n), stub))
+ self.interms[t - 1] = try_or_fail!(self, self.pow(n1, n2, "(**)"));
+ self.p += 1;
}
- }
- }
+ &ArithmeticInstruction::RDiv(ref a1, ref a2, t) => {
+ let stub = MachineError::functor_stub(clause_name!("(rdiv)"), 2);
- fn float_pow(&self, n1: Number, n2: Number) -> Result<Number, MachineStub> {
- let f1 = result_f(&n1, rnd_f);
- let f2 = result_f(&n2, rnd_f);
+ let (r1, stub) = try_or_fail!(self, self.get_rational(a1, stub));
+ let (r2, _) = try_or_fail!(self, self.get_rational(a2, stub));
- let stub = MachineError::functor_stub(clause_name!("(**)"), 2);
+ self.interms[t - 1] =
+ Number::Rational(Rc::new(try_or_fail!(self, self.rdiv(r1, r2))));
+ self.p += 1;
+ }
+ &ArithmeticInstruction::IntFloorDiv(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));
- let f1 = try_numeric_result!(self, f1, stub.clone())?;
- let f2 = try_numeric_result!(self, f2, stub.clone())?;
-
- let result = result_f(&Number::Float(OrderedFloat(f1.powf(f2))), rnd_f);
-
- Ok(Number::Float(OrderedFloat(try_numeric_result!(
- self, result, stub
- )?)))
- }
-
- fn pow(&self, n1: Number, n2: Number, culprit: &'static str) -> Result<Number, MachineStub> {
- if n2.is_negative() && n1.is_zero() {
- let stub = MachineError::functor_stub(clause_name!(culprit), 2);
- return Err(self.error_form(MachineError::evaluation_error(EvalError::Undefined), stub));
- }
-
- match (n1, n2) {
- (Number::Integer(n1), Number::Integer(n2)) => Ok(Number::Integer(binary_pow(n1, n2))),
- (n1, n2) => self.float_pow(n1, n2),
- }
- }
-
- fn unary_float_fn_template<FloatFn>(&self, n1: Number, f: FloatFn) -> Result<f64, MachineStub>
- where
- FloatFn: Fn(f64) -> f64,
- {
- let stub = MachineError::functor_stub(clause_name!("(is)"), 2);
-
- let f1 = try_numeric_result!(self, result_f(&n1, rnd_f), stub.clone())?;
- let f1 = result_f(&Number::Float(OrderedFloat(f(f1))), rnd_f);
-
- try_numeric_result!(self, f1, stub)
- }
-
- fn sin(&self, n1: Number) -> Result<f64, MachineStub> {
- self.unary_float_fn_template(n1, |f| f.sin())
- }
-
- fn cos(&self, n1: Number) -> Result<f64, MachineStub> {
- self.unary_float_fn_template(n1, |f| f.cos())
- }
-
- fn tan(&self, n1: Number) -> Result<f64, MachineStub> {
- self.unary_float_fn_template(n1, |f| f.tan())
- }
-
- fn log(&self, n1: Number) -> Result<f64, MachineStub> {
- self.unary_float_fn_template(n1, |f| f.log(f64::consts::E))
- }
-
- fn exp(&self, n1: Number) -> Result<f64, MachineStub> {
- self.unary_float_fn_template(n1, |f| f.exp())
- }
-
- fn asin(&self, n1: Number) -> Result<f64, MachineStub> {
- self.unary_float_fn_template(n1, |f| f.asin())
- }
-
- fn acos(&self, n1: Number) -> Result<f64, MachineStub> {
- self.unary_float_fn_template(n1, |f| f.acos())
- }
-
- fn atan(&self, n1: Number) -> Result<f64, MachineStub> {
- self.unary_float_fn_template(n1, |f| f.atan())
- }
-
- fn sqrt(&self, n1: Number) -> Result<f64, MachineStub> {
- if n1.is_negative() {
- let stub = MachineError::functor_stub(clause_name!("(is)"), 2);
- return Err(self.error_form(MachineError::evaluation_error(EvalError::Undefined), stub));
- }
-
- self.unary_float_fn_template(n1, |f| f.sqrt())
- }
-
- 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)
- }
-
- fn floor(&self, n1: Number) -> Integer {
- rnd_i(&n1).to_owned()
- }
-
- fn ceiling(&self, n1: Number) -> Integer {
- -self.floor(-n1)
- }
-
- fn truncate(&self, n: Number) -> Integer {
- if n.is_negative() {
- -self.floor(n.abs())
- } else {
- self.floor(n)
- }
- }
-
- fn round(&self, n: Number) -> Result<Integer, MachineStub> {
- let stub = MachineError::functor_stub(clause_name!("(is)"), 2);
-
- let result = n + Number::Float(OrderedFloat(0.5f64));
- let result = try_numeric_result!(self, result, stub)?;
-
- Ok(self.floor(result))
- }
-
- fn shr(&self, n1: Number, n2: Number) -> Result<Integer, MachineStub> {
- let stub = MachineError::functor_stub(clause_name!("(>>)"), 2);
-
- match (n1, n2) {
- (Number::Integer(n1), Number::Integer(n2)) => match n2.to_u32() {
- Some(n2) => Ok(n1 >> n2),
- _ => Ok(n1 >> u32::max_value()),
- },
- (Number::Integer(_), n2) => Err(self.error_form(
- MachineError::type_error(ValidType::Integer, Addr::Con(n2.to_constant())),
- stub,
- )),
- (n1, _) => Err(self.error_form(
- MachineError::type_error(ValidType::Integer, Addr::Con(n1.to_constant())),
- stub,
- )),
- }
- }
-
- fn shl(&self, n1: Number, n2: Number) -> Result<Integer, MachineStub> {
- let stub = MachineError::functor_stub(clause_name!("(<<)"), 2);
-
- match (n1, n2) {
- (Number::Integer(n1), Number::Integer(n2)) => match n2.to_u32() {
- Some(n2) => Ok(n1 << n2),
- _ => Ok(n1 << u32::max_value()),
- },
- (Number::Integer(_), n2) => Err(self.error_form(
- MachineError::type_error(ValidType::Integer, Addr::Con(n2.to_constant())),
- stub,
- )),
- (n1, _) => Err(self.error_form(
- MachineError::type_error(ValidType::Integer, Addr::Con(n1.to_constant())),
- stub,
- )),
- }
- }
-
- fn bitwise_complement(&self, n1: Number) -> Result<Integer, MachineStub> {
- let stub = MachineError::functor_stub(clause_name!("(\\)"), 2);
-
- match n1 {
- Number::Integer(n1) => Ok(!n1),
- _ => Err(self.error_form(
- MachineError::type_error(ValidType::Integer, Addr::Con(n1.to_constant())),
- stub,
- )),
- }
- }
-
- fn xor(&self, n1: Number, n2: Number) -> Result<Integer, MachineStub> {
- let stub = MachineError::functor_stub(clause_name!("(xor)"), 2);
-
- match (n1, n2) {
- (Number::Integer(n1), Number::Integer(n2)) => Ok(n1 ^ n2),
- (Number::Integer(_), n2) => Err(self.error_form(
- MachineError::type_error(ValidType::Integer, Addr::Con(n2.to_constant())),
- stub,
- )),
- (n1, _) => Err(self.error_form(
- MachineError::type_error(ValidType::Integer, Addr::Con(n1.to_constant())),
- stub,
- )),
- }
- }
-
- fn and(&self, n1: Number, n2: Number) -> Result<Integer, MachineStub> {
- let stub = MachineError::functor_stub(clause_name!("(/\\)"), 2);
-
- match (n1, n2) {
- (Number::Integer(n1), Number::Integer(n2)) => Ok(n1 & n2),
- (Number::Integer(_), n2) => Err(self.error_form(
- MachineError::type_error(ValidType::Integer, Addr::Con(n2.to_constant())),
- stub,
- )),
- (n1, _) => Err(self.error_form(
- MachineError::type_error(ValidType::Integer, Addr::Con(n1.to_constant())),
- stub,
- )),
- }
- }
-
- fn modulus(&self, x: Number, y: Number) -> Result<Integer, MachineStub> {
- let stub = MachineError::functor_stub(clause_name!("(mod)"), 2);
-
- match (x, y) {
- (Number::Integer(x), Number::Integer(y)) => {
- if y == 0 {
- Err(self
- .error_form(MachineError::evaluation_error(EvalError::ZeroDivisor), stub))
- } else {
- Ok(x.div_rem_floor(y).1)
- }
- }
- (Number::Integer(_), n2) => Err(self.error_form(
- MachineError::type_error(ValidType::Integer, Addr::Con(n2.to_constant())),
- stub,
- )),
- (n1, _) => Err(self.error_form(
- MachineError::type_error(ValidType::Integer, Addr::Con(n1.to_constant())),
- stub,
- )),
- }
- }
-
- fn max(&self, n1: Number, n2: Number) -> Result<Number, MachineStub> {
- match (n1, n2) {
- (Number::Integer(n1), Number::Integer(n2)) => {
- if n1 > n2 {
- Ok(Number::Integer(n1))
- } else {
- Ok(Number::Integer(n2))
- }
- }
- (n1, n2) => {
- let stub = MachineError::functor_stub(clause_name!("max"), 2);
-
- let f1 = try_numeric_result!(self, result_f(&n1, rnd_f), stub.clone())?;
- let f2 = try_numeric_result!(self, result_f(&n2, rnd_f), stub)?;
-
- Ok(Number::Float(max(OrderedFloat(f1), OrderedFloat(f2))))
- }
- }
- }
-
- fn min(&self, n1: Number, n2: Number) -> Result<Number, MachineStub> {
- match (n1, n2) {
- (Number::Integer(n1), Number::Integer(n2)) => {
- if n1 < n2 {
- Ok(Number::Integer(n1))
- } else {
- Ok(Number::Integer(n2))
- }
- }
- (n1, n2) => {
- let stub = MachineError::functor_stub(clause_name!("max"), 2);
-
- let f1 = try_numeric_result!(self, result_f(&n1, rnd_f), stub.clone())?;
- let f2 = try_numeric_result!(self, result_f(&n2, rnd_f), stub)?;
-
- Ok(Number::Float(min(OrderedFloat(f1), OrderedFloat(f2))))
- }
- }
- }
-
- fn sign(&self, n: Number) -> Integer {
- if n.is_positive() {
- Integer::from(1)
- } else if n.is_negative() {
- Integer::from(-1)
- } else {
- Integer::from(0)
- }
- }
-
- 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(n1 % n2)
- }
- }
- (Number::Integer(_), n2) => Err(self.error_form(
- MachineError::type_error(ValidType::Integer, Addr::Con(n2.to_constant())),
- stub,
- )),
- (n1, _) => Err(self.error_form(
- MachineError::type_error(ValidType::Integer, Addr::Con(n1.to_constant())),
- stub,
- )),
- }
- }
-
- 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(n1 | n2),
- (Number::Integer(_), n2) => Err(self.error_form(
- MachineError::type_error(ValidType::Integer, Addr::Con(n2.to_constant())),
- stub,
- )),
- (n1, _) => Err(self.error_form(
- MachineError::type_error(ValidType::Integer, Addr::Con(n1.to_constant())),
- stub,
- )),
- }
- }
-
- pub(super)
- fn execute_arith_instr(&mut self, instr: &ArithmeticInstruction) {
- let stub = MachineError::functor_stub(clause_name!("(is)"), 2);
-
- match instr {
- &ArithmeticInstruction::Add(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] = try_or_fail!(self, try_numeric_result!(self, n1 + n2, stub));
- self.p += 1;
- }
- &ArithmeticInstruction::Sub(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] = try_or_fail!(self, try_numeric_result!(self, n1 - n2, stub));
- self.p += 1;
- }
- &ArithmeticInstruction::Mul(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] = try_or_fail!(self, try_numeric_result!(self, n1 * n2, stub));
- self.p += 1;
- }
- &ArithmeticInstruction::Max(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] = try_or_fail!(self, self.max(n1, n2));
- self.p += 1;
- }
- &ArithmeticInstruction::Min(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] = try_or_fail!(self, self.min(n1, n2));
- self.p += 1;
- }
- &ArithmeticInstruction::IntPow(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] = try_or_fail!(self, self.int_pow(n1, n2));
- self.p += 1;
- }
- &ArithmeticInstruction::Gcd(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(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] = try_or_fail!(self, self.pow(n1, n2, "(**)"));
- self.p += 1;
- }
- &ArithmeticInstruction::RDiv(ref a1, ref a2, t) => {
- let stub = MachineError::functor_stub(clause_name!("(rdiv)"), 2);
-
- let r1 = try_or_fail!(self, self.get_rational(a1, &stub));
- let r2 = try_or_fail!(self, self.get_rational(a2, &stub));
-
- self.interms[t - 1] = Number::Rational(try_or_fail!(self, self.rdiv(r1, r2)));
- self.p += 1;
- }
- &ArithmeticInstruction::IntFloorDiv(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.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(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(try_or_fail!(self, self.idiv(n1, n2)));
+ Number::Integer(Rc::new(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(self.sign(n));
+ self.interms[t - 1] = Number::Integer(Rc::new(self.sign(n)));
self.p += 1;
}
&ArithmeticInstruction::Neg(ref a1, t) => {
let n1 = try_or_fail!(self, self.get_number(a1));
self.interms[t - 1] =
- Number::Integer(try_or_fail!(self, self.bitwise_complement(n1)));
+ Number::Integer(Rc::new(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(try_or_fail!(self, self.shr(n1, n2)));
+ self.interms[t - 1] =
+ Number::Integer(Rc::new(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(try_or_fail!(self, self.shl(n1, n2)));
+ self.interms[t - 1] =
+ Number::Integer(Rc::new(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(try_or_fail!(self, self.xor(n1, n2)));
+ self.interms[t - 1] =
+ Number::Integer(Rc::new(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(try_or_fail!(self, self.and(n1, n2)));
+ self.interms[t - 1] =
+ Number::Integer(Rc::new(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(try_or_fail!(self, self.or(n1, n2)));
+ self.interms[t - 1] =
+ Number::Integer(Rc::new(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(try_or_fail!(self, self.modulus(n1, n2)));
+ self.interms[t - 1] =
+ Number::Integer(Rc::new(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(try_or_fail!(self, self.remainder(n1, n2)));
+ self.interms[t - 1] =
+ Number::Integer(Rc::new(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(self.truncate(n1));
+ self.interms[t - 1] =
+ Number::Integer(Rc::new(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(try_or_fail!(self, self.round(n1)));
+ self.interms[t - 1] =
+ Number::Integer(Rc::new(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(self.ceiling(n1));
+ self.interms[t - 1] =
+ Number::Integer(Rc::new(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(self.floor(n1));
+ self.interms[t - 1] =
+ Number::Integer(Rc::new(self.floor(n1)));
self.p += 1;
}
&ArithmeticInstruction::Plus(ref a1, t) => {
match instr {
&FactInstruction::GetConstant(_, ref c, reg) => {
let addr = self[reg].clone();
- self.write_constant_to_var(addr, c.clone());
+ self.write_constant_to_var(addr, c);
}
&FactInstruction::GetList(_, reg) => {
let addr = self.store(self.deref(self[reg].clone()));
match addr {
- Addr::Con(Constant::String(n, s)) =>
- match self.flags.double_quotes {
- DoubleQuotes::Chars | DoubleQuotes::Codes
- if s.len() > n => {
- self.s = HeapPtr::StringChar(n, s);
- self.mode = MachineMode::Read;
- }
- _ => {
- self.fail = true
- }
- },
Addr::PStrLocation(h, n) => {
self.s = HeapPtr::PStrChar(h, n);
self.mode = MachineMode::Read;
_ => self.fail = true,
};
}
- &FactInstruction::GetVariable(norm, arg) => self[norm] = self.registers[arg].clone(),
+ &FactInstruction::GetVariable(norm, arg) => {
+ self[norm] = self.registers[arg].clone();
+ }
&FactInstruction::GetValue(norm, arg) => {
let norm_addr = self[norm].clone();
let reg_addr = self.registers[arg].clone();
match self.mode {
MachineMode::Read => {
let addr = self.s.read(&self.heap);
- self.write_constant_to_var(addr, c.clone());
+ self.write_constant_to_var(addr, c);
}
MachineMode::Write => {
- self.heap.push(HeapCellValue::Addr(Addr::Con(c.clone())));
+ self.heap.put_constant(c.clone());
}
};
if let Addr::HeapCell(hc) = addr {
if hc < h {
- let val = self.heap[hc].clone();
+ let val = self.heap.clone(hc);
self.heap.push(val);
self.increment_s_ptr(1);
&FactInstruction::UnifyValue(reg) => {
match self.mode {
MachineMode::Read => {
- let reg_addr = self[reg].clone();
+ let reg_addr = self[reg];
self.unify(reg_addr, self.s.read(&self.heap));
}
MachineMode::Write => {
fn execute_indexing_instr(&mut self, instr: &IndexingInstruction) {
match instr {
&IndexingInstruction::SwitchOnTerm(v, c, l, s) => {
- let a1 = self.registers[1].clone();
- let addr = self.store(self.deref(a1));
+ let addr = self[temp_v!(1)];
+ let addr = self.store(self.deref(addr));
let offset = match addr {
Addr::HeapCell(_) | Addr::StackCell(..)
| Addr::AttrVar(..) | Addr::Stream(_) => {
- v
- }
- Addr::Con(Constant::String(n, ref s)) => {
+ v
+ }
+ Addr::PStrLocation(..) => {
if !self.flags.double_quotes.is_atom() {
- if n >= s.len() {
- c
- } else {
- l
- }
+ l
} else {
c
}
}
- Addr::Con(_) => {
- c
- }
- Addr::Lis(_) | Addr::PStrLocation(..) => {
+ Addr::Char(_) | Addr::CharCode(_) | Addr::Con(_) | Addr::CutPoint(_)
+ | Addr::EmptyList | Addr::Float(_) | Addr::Usize(_) => {
+ c
+ }
+ Addr::Lis(_) => {
l
}
Addr::Str(_) => {
s
}
- Addr::DBRef(_) => {
- self.fail = true;
- return;
- }
};
match offset {
};
}
&IndexingInstruction::SwitchOnConstant(_, ref hm) => {
- let a1 = self.registers[1].clone();
- let addr = self.store(self.deref(a1));
+ let addr = self[temp_v!(1)];
+ let addr = self.store(self.deref(addr));
- let offset = match addr {
- Addr::Con(constant) => match hm.get(&constant) {
- Some(offset) => *offset,
- _ => 0,
- },
- _ => 0,
- };
+ let offset =
+ match addr.as_constant(&self) {
+ Some(c) => {
+ match hm.get(&c) {
+ Some(offset) => *offset,
+ _ => 0,
+ }
+ }
+ None => {
+ 0
+ }
+ };
match offset {
0 => self.fail = true,
0
}
}
- _ => 0,
+ _ => {
+ 0
+ }
};
match offset {
pub(super) fn execute_query_instr(&mut self, instr: &QueryInstruction) {
match instr {
- &QueryInstruction::GetVariable(norm, arg) => self[norm] = self.registers[arg].clone(),
- &QueryInstruction::PutConstant(_, ref constant, reg) => {
- self[reg] = Addr::Con(constant.clone())
+ &QueryInstruction::GetVariable(norm, arg) => {
+ self[norm] = self.registers[arg].clone();
+ }
+ &QueryInstruction::PutConstant(_, ref c, reg) => {
+ self[reg] = self.heap.put_constant(c.clone());
+ }
+ &QueryInstruction::PutList(_, reg) => {
+ self[reg] = Addr::Lis(self.heap.h());
}
- &QueryInstruction::PutList(_, reg) => self[reg] = Addr::Lis(self.heap.h()),
&QueryInstruction::PutStructure(ref ct, arity, reg) => {
let h = self.heap.h();
self.registers[arg] = self.heap[h].as_addr(h);
}
}
- &QueryInstruction::PutValue(norm, arg) => self.registers[arg] = self[norm].clone(),
+ &QueryInstruction::PutValue(norm, arg) => {
+ self.registers[arg] = self[norm].clone();
+ }
&QueryInstruction::PutVariable(norm, arg) => {
match norm {
RegType::Perm(n) => {
let e = self.e;
self[norm] = Addr::StackCell(e, n);
- self.registers[arg] = self[norm].clone();
+ self.registers[arg] = self[norm];
}
RegType::Temp(_) => {
let h = self.heap.h();
};
}
&QueryInstruction::SetConstant(ref c) => {
- self.heap.push(HeapCellValue::Addr(Addr::Con(c.clone())));
+ self.heap.put_constant(c.clone());
}
&QueryInstruction::SetLocalValue(reg) => {
- let addr = self.deref(self[reg].clone());
+ let addr = self.deref(self[reg]);
let h = self.heap.h();
if addr < Ref::HeapCell(h) {
}
pub(super) fn setup_call_n(&mut self, arity: usize) -> Option<PredicateKey> {
- let stub = MachineError::functor_stub(clause_name!("call"), arity + 1);
let addr = self.store(self.deref(self.registers[arity].clone()));
let (name, narity) = match addr {
Addr::Str(a) => {
- let result = self.heap[a].clone();
+ let result = self.heap.clone(a);
if let HeapCellValue::NamedStr(narity, name, _) = result {
+ let stub = MachineError::functor_stub(clause_name!("call"), arity + 1);
+
if narity + arity > 63 {
let representation_error = self.error_form(
MachineError::representation_error(RepFlag::MaxArity),
return None;
}
}
- Addr::Con(Constant::Atom(name, _)) => (name, 0),
+ Addr::Con(h) =>
+ match &self.heap[h] {
+ HeapCellValue::Atom(ref name, _) => {
+ (name.clone(), 0)
+ }
+ _ => {
+ self.fail = true;
+ return None;
+ }
+ }
Addr::HeapCell(_) | Addr::StackCell(_, _) => {
- let instantiation_error =
- self.error_form(MachineError::instantiation_error(), stub);
- self.throw_exception(instantiation_error);
+ let stub = MachineError::functor_stub(clause_name!("call"), arity + 1);
+ let instantiation_error = self.error_form(
+ MachineError::instantiation_error(),
+ stub,
+ );
+ self.throw_exception(instantiation_error);
return None;
}
_ => {
- let type_error =
- self.error_form(MachineError::type_error(ValidType::Callable, addr), stub);
- self.throw_exception(type_error);
+ let stub = MachineError::functor_stub(clause_name!("call"), arity + 1);
+ let type_error = self.error_form(
+ MachineError::type_error(self.heap.h(), ValidType::Callable, addr),
+ stub,
+ );
+ self.throw_exception(type_error);
return None;
}
};
// arg(+N, +Term, ?Arg)
pub(super) fn try_arg(&mut self) -> CallResult {
let stub = MachineError::functor_stub(clause_name!("arg"), 3);
- let n = self.store(self.deref(self[temp_v!(1)].clone()));
+ let n = self.store(self.deref(self[temp_v!(1)]));
match n {
- Addr::HeapCell(_) | Addr::StackCell(..) =>
- // 8.5.2.3 a)
- {
+ Addr::HeapCell(_) | Addr::StackCell(..) => { // 8.5.2.3 a)
return Err(self.error_form(MachineError::instantiation_error(), stub))
}
- Addr::Con(Constant::Integer(n)) => {
- if n < 0 {
- // 8.5.2.3 e)
- let n = Addr::Con(Constant::Integer(n));
- let dom_err = MachineError::domain_error(DomainError::NotLessThanZero, n);
-
- return Err(self.error_form(dom_err, 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,
+ );
- let n = match n.to_usize() {
- Some(n) => n,
- None => {
- self.fail = true;
- return Ok(());
+ return Err(self.error_form(dom_err, stub));
}
- };
- let term = self.store(self.deref(self[temp_v!(2)].clone()));
+ let n = match n.to_usize() {
+ Some(n) => n,
+ None => {
+ self.fail = true;
+ return Ok(());
+ }
+ };
- 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[o].clone() {
- HeapCellValue::NamedStr(arity, _, _) if 1 <= n && n <= arity => {
- let a3 = self[temp_v!(3)].clone();
- let h_a = Addr::HeapCell(o + n);
+ let term = self.store(self.deref(self[temp_v!(2)].clone()));
- self.unify(a3, h_a);
+ match term {
+ Addr::HeapCell(_) | Addr::StackCell(..) => { // 8.5.2.3 b)
+ return Err(self.error_form(MachineError::instantiation_error(), stub))
}
- _ => self.fail = true,
- },
- Addr::Lis(l) => {
- if n == 1 || n == 2 {
- let a3 = self[temp_v!(3)].clone();
- let h_a = Addr::HeapCell(l + n - 1);
+ Addr::Str(o) => match self.heap.clone(o) {
+ HeapCellValue::NamedStr(arity, _, _) if 1 <= n && n <= arity => {
+ let a3 = self[temp_v!(3)].clone();
+ let h_a = Addr::HeapCell(o + n);
- self.unify(a3, h_a);
- } else {
- self.fail = true;
- }
- }
- Addr::PStrLocation(h, offset) => {
- if n == 1 || n == 2 {
- let a3 = self[temp_v!(3)].clone();
- let h_a =
- if let HeapCellValue::PartialString(ref pstr) = &self.heap[h] {
- let s = pstr.block_as_str();
+ self.unify(a3, h_a);
+ }
+ _ => self.fail = true,
+ },
+ Addr::Lis(l) => {
+ if n == 1 || n == 2 {
+ let a3 = self[temp_v!(3)].clone();
+ let h_a = Addr::HeapCell(l + n - 1);
- if let Some(c) = s[offset ..].chars().next() {
- if n == 1 {
- Addr::Con(Constant::Char(c))
+ self.unify(a3, h_a);
+ } else {
+ self.fail = true;
+ }
+ }
+ Addr::PStrLocation(h, offset) => {
+ if n == 1 || n == 2 {
+ let a3 = self[temp_v!(3)].clone();
+ 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())
+ }
} else {
- Addr::PStrLocation(h, offset + c.len_utf8())
+ unreachable!()
}
} else {
unreachable!()
- }
- } else {
- unreachable!()
- };
+ };
- self.unify(a3, h_a);
- } else {
- self.fail = true;
- }
- }
- Addr::Con(Constant::String(o, ref s))
- if !self.flags.double_quotes.is_atom() && !s[o ..].is_empty() =>
- {
- if n == 1 || n == 2 {
- let a3 = self[temp_v!(3)].clone();
- let c = s[o ..].chars().next().unwrap();
-
- let h_a = if n == 1 {
- Addr::Con(Constant::Char(c))
+ self.unify(a3, h_a);
} else {
- Addr::Con(Constant::String(o + c.len_utf8(), s.clone()))
- };
-
- self.unify(a3, h_a);
- } else {
- self.fail = true;
+ self.fail = true;
+ }
+ }
+ _ => { // 8.5.2.3 d)
+ return Err(self.error_form(
+ MachineError::type_error(
+ self.heap.h(),
+ ValidType::Compound,
+ term,
+ ),
+ stub,
+ ))
}
}
- _ =>
- // 8.5.2.3 d)
- {
- return Err(self.error_form(
- MachineError::type_error(ValidType::Compound, term),
- stub,
- ))
- }
+ } else {
+ return Err(self.error_form(
+ MachineError::type_error(
+ self.heap.h(),
+ ValidType::Integer,
+ Addr::Con(h),
+ ),
+ stub,
+ ))
}
}
- _ =>
- // 8.5.2.3 c)
- {
+ _ => { // 8.5.2.3 c)
return Err(self.error_form(
- MachineError::type_error(ValidType::Integer, n),
+ MachineError::type_error(
+ self.heap.h(),
+ ValidType::Integer,
+ n,
+ ),
stub,
))
}
let a2 = self[temp_v!(2)].clone();
match self.compare_term_test(&a1, &a2) {
- Ordering::Greater => match qt {
+ Some(Ordering::Greater) => match qt {
CompareTermQT::GreaterThan | CompareTermQT::GreaterThanOrEqual => return,
_ => self.fail = true,
},
- Ordering::Equal => match qt {
+ Some(Ordering::Equal) => match qt {
CompareTermQT::GreaterThanOrEqual | CompareTermQT::LessThanOrEqual => return,
_ => self.fail = true,
},
- Ordering::Less => match qt {
+ Some(Ordering::Less) => match qt {
CompareTermQT::LessThan | CompareTermQT::LessThanOrEqual => return,
_ => self.fail = true,
},
+ None => {
+ self.fail = true;
+ }
};
}
while let Some((v1, v2)) = iter.next() {
match (v1, v2) {
- (HeapCellValue::NamedStr(ar1, n1, _), HeapCellValue::NamedStr(ar2, n2, _)) =>
- if ar1 != ar2 || n1 != n2 {
- return true;
- },
- (HeapCellValue::Addr(Addr::PStrLocation(..)),
- HeapCellValue::Addr(Addr::PStrLocation(..))) =>
- continue,
- (HeapCellValue::Addr(Addr::PStrLocation(..)),
- HeapCellValue::Addr(Addr::Con(Constant::String(..))))
- | (HeapCellValue::Addr(Addr::Con(Constant::String(..))),
- HeapCellValue::Addr(Addr::PStrLocation(..)))
- if self.flags.double_quotes.is_chars() => {
+ (Addr::Str(s1), Addr::Str(s2)) => {
+ if let HeapCellValue::NamedStr(ar1, n1, _) = &self.heap[s1] {
+ if let HeapCellValue::NamedStr(ar2, n2, _) = &self.heap[s2] {
+ if ar1 != ar2 || n1 != n2 {
+ return true;
+ }
+ } else {
+ unreachable!()
+ }
+ } else {
+ unreachable!()
+ }
+ }
+ (Addr::PStrLocation(..), Addr::Lis(_))
+ | (Addr::Lis(_), Addr::PStrLocation(..))
+ if !self.flags.double_quotes.is_atom() => {
continue;
}
- (HeapCellValue::Addr(Addr::Lis(_)), HeapCellValue::Addr(Addr::Lis(_))) =>
- continue,
- (HeapCellValue::Addr(Addr::Con(Constant::EmptyList)),
- HeapCellValue::Addr(Addr::Con(Constant::String(n, s))))
- | (HeapCellValue::Addr(Addr::Con(Constant::String(n, s))),
- HeapCellValue::Addr(Addr::Con(Constant::EmptyList))) =>
- return match self.flags.double_quotes {
- DoubleQuotes::Atom => true,
- _ => n < s.len()
- },
- (HeapCellValue::Addr(a1), HeapCellValue::Addr(a2)) =>
+ (Addr::PStrLocation(..), Addr::PStrLocation(..)) => {
+ continue;
+ }
+ (Addr::Lis(_), Addr::Lis(_)) => {
+ continue;
+ }
+ (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),
+ ) => {
+ if n1 != n2 {
+ return true;
+ }
+ }
+ (
+ &HeapCellValue::DBRef(ref db_ref_1),
+ &HeapCellValue::DBRef(ref db_ref_2),
+ ) => {
+ if db_ref_1 != db_ref_2 {
+ return true;
+ }
+ }
+ (
+ &HeapCellValue::Atom(ref n1, ref spec_1),
+ &HeapCellValue::Atom(ref n2, ref spec_2),
+ ) => {
+ if n1 != n2 || spec_1 != spec_2 {
+ return true;
+ }
+ }
+ _ => {
+ return true;
+ }
+ }
+ }
+ (a1, a2) => {
if a1 != a2 {
return true;
- },
- _ => return true,
+ }
+ }
}
}
iter.first_to_expire != Ordering::Equal
}
- pub(super) fn compare_term_test(&self, a1: &Addr, a2: &Addr) -> Ordering {
+ pub(super) fn compare_term_test(&self, a1: &Addr, a2: &Addr) -> Option<Ordering> {
let mut iter = self.zipped_acyclic_pre_order_iter(a1.clone(), a2.clone());
while let Some((v1, v2)) = iter.next() {
- match (v1, v2) {
- (
- HeapCellValue::Addr(Addr::Lis(_)),
- HeapCellValue::Addr(Addr::PStrLocation(..)),
- )
- | (
- HeapCellValue::Addr(Addr::PStrLocation(..)),
- HeapCellValue::Addr(Addr::Lis(_)),
- )
- | (
- HeapCellValue::Addr(Addr::PStrLocation(..)),
- HeapCellValue::Addr(Addr::PStrLocation(..)),
- ) => {
- }
- (
- HeapCellValue::Addr(Addr::PStrLocation(..)),
- HeapCellValue::Addr(Addr::Con(Constant::String(..))),
- )
- | (
- HeapCellValue::Addr(Addr::Con(Constant::String(..))),
- HeapCellValue::Addr(Addr::PStrLocation(..)),
- ) if self.flags.double_quotes.is_chars() => {
- }
- (
- HeapCellValue::Addr(Addr::Lis(_)),
- HeapCellValue::Addr(Addr::Con(Constant::String(..))),
- )
- | (
- HeapCellValue::Addr(Addr::Con(Constant::String(..))),
- HeapCellValue::Addr(Addr::Lis(_)),
- ) if !self.flags.double_quotes.is_atom() => {
- }
- (
- HeapCellValue::Addr(Addr::Con(Constant::EmptyList)),
- HeapCellValue::Addr(Addr::Con(Constant::String(n, ref s))),
- ) if !self.flags.double_quotes.is_atom() => {
- if s[n ..].is_empty() {
- return Ordering::Equal;
- } else {
- return Ordering::Greater;
- }
- }
- (
- HeapCellValue::Addr(Addr::Con(Constant::Char(c1))),
- HeapCellValue::Addr(Addr::Con(Constant::Char(c2))),
- ) => {
- if c1 != c2 {
- return c1.cmp(&c2);
- }
- }
- (
- HeapCellValue::Addr(Addr::Con(Constant::Atom(atom, _))),
- HeapCellValue::Addr(Addr::Con(Constant::Char(c))),
- ) => {
- return if atom.as_str().chars().count() == 1 {
- atom.as_str().chars().next().cmp(&Some(c))
- } else {
- Ordering::Greater
- }
- }
- (
- HeapCellValue::Addr(Addr::Con(Constant::Char(c))),
- HeapCellValue::Addr(Addr::Con(Constant::Atom(atom, _))),
- ) => {
- return if atom.as_str().chars().count() == 1 {
- Some(c).cmp(&atom.as_str().chars().next())
- } else {
- Ordering::Less
+ let order_cat_v1 = v1.order_category(&self.heap);
+ let order_cat_v2 = v2.order_category(&self.heap);
+
+ if order_cat_v1 != order_cat_v1 {
+ return Some(order_cat_v1.cmp(&order_cat_v2));
+ }
+
+ match order_cat_v1 {
+ Some(TermOrderCategory::Variable) => {
+ let v1 = v1.as_var().unwrap();
+ let v2 = v2.as_var().unwrap();
+
+ if v1 != v2 {
+ return Some(v1.cmp(&v2));
}
}
- (
- HeapCellValue::Addr(Addr::Con(Constant::String(n, ref s))),
- HeapCellValue::Addr(Addr::Con(Constant::EmptyList)),
- ) if !self.flags.double_quotes.is_atom() => {
- if s[n ..].is_empty() {
- return Ordering::Equal;
+ Some(TermOrderCategory::FloatingPoint) => {
+ if let Addr::Float(f1) = v1 {
+ if let Addr::Float(f2) = v2 {
+ return Some(f1.cmp(&f2));
+ } else {
+ unreachable!()
+ }
} else {
- return Ordering::Less;
- }
- }
- (
- HeapCellValue::Addr(Addr::HeapCell(hc1)),
- HeapCellValue::Addr(Addr::HeapCell(hc2)),
- )
- | (
- HeapCellValue::Addr(Addr::AttrVar(hc1)),
- HeapCellValue::Addr(Addr::HeapCell(hc2)),
- )
- | (
- HeapCellValue::Addr(Addr::HeapCell(hc1)),
- HeapCellValue::Addr(Addr::AttrVar(hc2)),
- )
- | (
- HeapCellValue::Addr(Addr::AttrVar(hc1)),
- HeapCellValue::Addr(Addr::AttrVar(hc2)),
- ) => {
- if hc1 != hc2 {
- return hc1.cmp(&hc2);
- }
- }
- (HeapCellValue::Addr(Addr::HeapCell(_)), _)
- | (HeapCellValue::Addr(Addr::AttrVar(_)), _) => {
- return Ordering::Less;
- }
- (
- HeapCellValue::Addr(Addr::StackCell(fr1, sc1)),
- HeapCellValue::Addr(Addr::StackCell(fr2, sc2)),
- ) => {
- if fr1 > fr2 {
- return Ordering::Greater;
- } else if fr1 < fr2 || sc1 < sc2 {
- return Ordering::Less;
- } else if sc1 > sc2 {
- return Ordering::Greater;
- }
- }
- (
- HeapCellValue::Addr(Addr::StackCell(..)),
- HeapCellValue::Addr(Addr::HeapCell(_)),
- )
- | (
- HeapCellValue::Addr(Addr::StackCell(..)),
- HeapCellValue::Addr(Addr::AttrVar(_)),
- ) => {
- return Ordering::Greater;
- }
- (HeapCellValue::Addr(Addr::StackCell(..)), _) => {
- return Ordering::Less;
- }
- (
- HeapCellValue::Addr(Addr::Con(Constant::Integer(..))),
- HeapCellValue::Addr(Addr::HeapCell(_)),
- )
- | (
- HeapCellValue::Addr(Addr::Con(Constant::Integer(..))),
- HeapCellValue::Addr(Addr::AttrVar(_)),
- ) => {
- return Ordering::Greater;
- }
- (
- HeapCellValue::Addr(Addr::Con(Constant::Integer(..))),
- HeapCellValue::Addr(Addr::StackCell(..)),
- ) => {
- return Ordering::Greater;
- }
- (
- HeapCellValue::Addr(Addr::Con(Constant::Integer(n1))),
- HeapCellValue::Addr(Addr::Con(Constant::Integer(n2))),
- ) => {
- if n1 != n2 {
- return n1.cmp(&n2);
- }
- }
- (HeapCellValue::Addr(Addr::Con(Constant::Integer(_))), _) => {
- return Ordering::Less;
- }
- (
- HeapCellValue::Addr(Addr::Con(Constant::Float(..))),
- HeapCellValue::Addr(Addr::HeapCell(_)),
- )
- | (
- HeapCellValue::Addr(Addr::Con(Constant::Float(..))),
- HeapCellValue::Addr(Addr::AttrVar(_)),
- ) => {
- return Ordering::Greater;
- }
- (
- HeapCellValue::Addr(Addr::Con(Constant::Float(..))),
- HeapCellValue::Addr(Addr::StackCell(..)),
- ) => {
- return Ordering::Greater;
- }
- (
- HeapCellValue::Addr(Addr::Con(Constant::Float(n1))),
- HeapCellValue::Addr(Addr::Con(Constant::Float(n2))),
- ) => {
- if n1 != n2 {
- return n1.cmp(&n2);
- }
- }
- (HeapCellValue::Addr(Addr::Con(Constant::Float(_))), _) => return Ordering::Less,
- (
- HeapCellValue::Addr(Addr::Con(Constant::Rational(..))),
- HeapCellValue::Addr(Addr::HeapCell(_)),
- )
- | (
- HeapCellValue::Addr(Addr::Con(Constant::Rational(..))),
- HeapCellValue::Addr(Addr::AttrVar(_)),
- ) => {
- return Ordering::Greater;
- }
- (
- HeapCellValue::Addr(Addr::Con(Constant::Rational(..))),
- HeapCellValue::Addr(Addr::StackCell(..)),
- ) => {
- return Ordering::Greater;
- }
- (
- HeapCellValue::Addr(Addr::Con(Constant::Rational(n1))),
- HeapCellValue::Addr(Addr::Con(Constant::Rational(n2))),
- ) => {
- if n1 != n2 {
- return n1.cmp(&n2);
+ unreachable!()
}
}
- (HeapCellValue::Addr(Addr::Con(Constant::Rational(_))), _) => {
- return Ordering::Less
- }
- (
- HeapCellValue::Addr(Addr::Con(Constant::String(..))),
- HeapCellValue::Addr(Addr::HeapCell(_)),
- )
- | (
- HeapCellValue::Addr(Addr::Con(Constant::String(..))),
- HeapCellValue::Addr(Addr::AttrVar(_)),
- ) => {
- return Ordering::Greater;
- }
- (
- HeapCellValue::Addr(Addr::Con(Constant::String(..))),
- HeapCellValue::Addr(Addr::StackCell(..)),
- ) => {
- return Ordering::Greater;
- }
- (
- HeapCellValue::Addr(Addr::Con(Constant::String(..))),
- HeapCellValue::Addr(Addr::Con(Constant::Integer(_))),
- ) => {
- return Ordering::Greater;
- }
- (
- HeapCellValue::Addr(Addr::Con(Constant::String(..))),
- HeapCellValue::Addr(Addr::Con(Constant::Rational(_))),
- ) => {
- return Ordering::Greater;
- }
- (
- HeapCellValue::Addr(Addr::Con(Constant::String(..))),
- HeapCellValue::Addr(Addr::Con(Constant::Float(_))),
- ) => {
- return Ordering::Greater;
- }
- (
- HeapCellValue::Addr(Addr::Con(Constant::String(n1, s1))),
- HeapCellValue::Addr(Addr::Con(Constant::String(n2, s2))),
- ) => {
- return s1[n1 ..].cmp(&s2[n2 ..]);
- }
- (HeapCellValue::Addr(Addr::Con(Constant::String(..))), _) => {
- return Ordering::Less;
- }
- (
- HeapCellValue::Addr(Addr::Con(Constant::Atom(..))),
- HeapCellValue::Addr(Addr::HeapCell(_)),
- )
- | (
- HeapCellValue::Addr(Addr::Con(Constant::Atom(..))),
- HeapCellValue::Addr(Addr::AttrVar(_)),
- ) => return Ordering::Greater,
- (
- HeapCellValue::Addr(Addr::Con(Constant::Atom(..))),
- HeapCellValue::Addr(Addr::StackCell(..)),
- ) => return Ordering::Greater,
- (
- HeapCellValue::Addr(Addr::Con(Constant::Atom(..))),
- HeapCellValue::Addr(Addr::Con(Constant::Float(_))),
- ) => return Ordering::Greater,
- (
- HeapCellValue::Addr(Addr::Con(Constant::Atom(..))),
- HeapCellValue::Addr(Addr::Con(Constant::Integer(_))),
- ) => return Ordering::Greater,
- (
- HeapCellValue::Addr(Addr::Con(Constant::Atom(..))),
- HeapCellValue::Addr(Addr::Con(Constant::Rational(_))),
- ) => return Ordering::Greater,
- (
- HeapCellValue::Addr(Addr::Con(Constant::Atom(..))),
- HeapCellValue::Addr(Addr::Con(Constant::String(..))),
- ) => return Ordering::Greater,
- (
- HeapCellValue::Addr(Addr::Con(Constant::Atom(s1, _))),
- HeapCellValue::Addr(Addr::Con(Constant::Atom(s2, _))),
- ) => {
- if s1 != s2 {
- return s1.cmp(&s2);
+ Some(TermOrderCategory::Integer) => {
+ match (v1, v2) {
+ (
+ 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));
+ }
+ }
+ _ => {
+ unreachable!()
+ }
+ }
+ }
+ _ => {
+ unreachable!()
+ }
}
}
- (HeapCellValue::Addr(Addr::Con(Constant::Atom(..))), _) => {
- return Ordering::Less;
- }
- (HeapCellValue::NamedStr(ar1, n1, _), HeapCellValue::NamedStr(ar2, n2, _)) => {
- if ar1 < ar2 {
- return Ordering::Less;
- } else if ar1 > ar2 {
- return Ordering::Greater;
- } else if n1 != n2 {
- return n1.cmp(&n2);
+ Some(TermOrderCategory::Atom) => {
+ match (v1, v2) {
+ (
+ Addr::Con(h1),
+ Addr::Con(h2),
+ ) => {
+ if let HeapCellValue::Atom(ref n1, _) = &self.heap[h1] {
+ if let HeapCellValue::Atom(ref n2, _) = &self.heap[h2] {
+ if n1 != n2 {
+ return Some(n1.cmp(&n2));
+ }
+ } else {
+ unreachable!()
+ }
+ } else {
+ unreachable!()
+ }
+ }
+ (
+ Addr::Con(h1),
+ Addr::Char(c),
+ ) => {
+ if let HeapCellValue::Atom(ref n1, _) = &self.heap[h1] {
+ if n1.is_char() {
+ if n1.as_str().chars().next() != Some(c) {
+ return Some(n1.as_str().chars().next().cmp(&Some(c)));
+ }
+ } else {
+ return Some(Ordering::Greater);
+ }
+ } else {
+ unreachable!()
+ }
+ }
+ (
+ Addr::Char(c),
+ Addr::Con(h1),
+ ) => {
+ if let HeapCellValue::Atom(ref n1, _) = &self.heap[h1] {
+ if n1.is_char() {
+ if n1.as_str().chars().next() != Some(c) {
+ return Some(Some(c).cmp(&n1.as_str().chars().next()));
+ }
+ } else {
+ return Some(Ordering::Less);
+ }
+ } else {
+ unreachable!()
+ }
+ }
+ (
+ Addr::Con(h),
+ Addr::CharCode(c),
+ ) => {
+ let c = std::char::from_u32(c).unwrap();
+
+ if let HeapCellValue::Atom(ref n1, _) = &self.heap[h] {
+ if n1.is_char() {
+ if n1.as_str().chars().next() != Some(c) {
+ return Some(n1.as_str().chars().next().cmp(&Some(c)));
+ }
+ } else {
+ return Some(Ordering::Greater);
+ }
+ } else {
+ unreachable!()
+ }
+ }
+ (
+ Addr::CharCode(c),
+ Addr::Con(h),
+ ) => {
+ let c = std::char::from_u32(c).unwrap();
+
+ if let HeapCellValue::Atom(ref n1, _) = &self.heap[h] {
+ if n1.is_char() {
+ if n1.as_str().chars().next() != Some(c) {
+ return Some(Some(c).cmp(&n1.as_str().chars().next()));
+ }
+ } else {
+ return Some(Ordering::Less);
+ }
+ } else {
+ unreachable!()
+ }
+ }
+ (
+ Addr::EmptyList,
+ Addr::Con(h),
+ ) => {
+ if let HeapCellValue::Atom(ref n1, _) = &self.heap[h] {
+ if "[]" != n1.as_str() {
+ return Some("[]".cmp(n1.as_str()));
+ }
+ } else {
+ unreachable!()
+ }
+ }
+ (
+ Addr::Con(h),
+ Addr::EmptyList,
+ ) => {
+ if let HeapCellValue::Atom(ref n1, _) = &self.heap[h] {
+ if "[]" != n1.as_str() {
+ return Some(n1.as_str().cmp("[]"));
+ }
+ } else {
+ unreachable!()
+ }
+ }
+ (
+ Addr::Char(c1),
+ Addr::Char(c2),
+ ) => {
+ if c1 != c2 {
+ return Some(c1.cmp(&c2));
+ }
+ }
+ (
+ Addr::CharCode(c1),
+ Addr::CharCode(c2),
+ ) => {
+ if c1 != c2 {
+ return Some(c1.cmp(&c2));
+ }
+ }
+ (
+ Addr::Char(c1),
+ Addr::CharCode(c2),
+ ) => {
+ let c2 = std::char::from_u32(c2).unwrap();
+
+ if c1 != c2 {
+ return Some(c1.cmp(&c2));
+ }
+ }
+ (
+ Addr::CharCode(c1),
+ Addr::Char(c2),
+ ) => {
+ let c1 = std::char::from_u32(c1).unwrap();
+
+ if c1 != c2 {
+ return Some(c1.cmp(&c2));
+ }
+ }
+ (
+ Addr::Char(c),
+ Addr::EmptyList,
+ ) => {
+ return if c == '[' {
+ Some(Ordering::Less)
+ } else {
+ Some(c.cmp(&'['))
+ };
+ }
+ (
+ Addr::EmptyList,
+ Addr::Char(c),
+ ) => {
+ return if c == '[' {
+ Some(Ordering::Greater)
+ } else {
+ Some('['.cmp(&c))
+ };
+ }
+ (
+ Addr::CharCode(c),
+ Addr::EmptyList,
+ ) => {
+ let c = std::char::from_u32(c).unwrap();
+
+ return if c == '[' {
+ Some(Ordering::Less)
+ } else {
+ Some(c.cmp(&'['))
+ };
+ }
+ (
+ Addr::EmptyList,
+ Addr::CharCode(c),
+ ) => {
+ let c = std::char::from_u32(c).unwrap();
+
+ return if c == '[' {
+ Some(Ordering::Greater)
+ } else {
+ Some('['.cmp(&c))
+ };
+ }
+ _ => {
+ return None;
+ }
}
}
- (HeapCellValue::Addr(Addr::Lis(_)), HeapCellValue::Addr(Addr::Lis(_))) => {
- continue;
- }
- (HeapCellValue::Addr(Addr::Lis(_)), HeapCellValue::NamedStr(ar, n, _))
- | (HeapCellValue::NamedStr(ar, n, _), HeapCellValue::Addr(Addr::Lis(_))) => {
- if ar == 2 && n.as_str() == "." {
- continue;
- } else if ar < 2 {
- return Ordering::Greater;
- } else if ar > 2 {
- return Ordering::Less;
- } else {
- return n.as_str().cmp(".");
+ Some(TermOrderCategory::Compound) => {
+ match (v1, v2) {
+ (
+ Addr::Lis(_),
+ Addr::Lis(_),
+ ) => {
+ }
+ (
+ Addr::PStrLocation(..),
+ Addr::PStrLocation(..),
+ ) => {
+ }
+ (
+ Addr::Str(h1),
+ Addr::Str(h2),
+ ) => {
+ if let HeapCellValue::NamedStr(a1, ref n1, _) = &self.heap[h1] {
+ if let HeapCellValue::NamedStr(a2, ref n2, _) = &self.heap[h2] {
+ if a1 != a2 || n1.as_str() != n2.as_str() {
+ return Some(a1.cmp(&a2).then_with(|| n1.as_str().cmp(n2.as_str())));
+ }
+ } else {
+ unreachable!()
+ }
+ } else {
+ unreachable!()
+ }
+ }
+ (
+ Addr::Lis(_),
+ Addr::PStrLocation(..),
+ ) |
+ (
+ Addr::PStrLocation(..),
+ Addr::Lis(_),
+ ) if !self.flags.double_quotes.is_atom() => {
+ }
+ (
+ Addr::Lis(_),
+ Addr::Str(s),
+ ) => {
+ if let &HeapCellValue::NamedStr(a1, ref n1, _) = &self.heap[s] {
+ if a1 != 2 || n1.as_str() != "." {
+ return Some(a1.cmp(&2).then_with(|| n1.as_str().cmp(".")));
+ }
+ } else {
+ unreachable!()
+ }
+ }
+ (
+ Addr::Str(s),
+ Addr::Lis(_),
+ ) => {
+ if let &HeapCellValue::NamedStr(a1, ref n1, _) = &self.heap[s] {
+ if a1 != 2 || n1.as_str() != "." {
+ return Some(2.cmp(&a1).then_with(|| ".".cmp(n1.as_str())));
+ }
+ } else {
+ unreachable!()
+ }
+ }
+ (
+ Addr::PStrLocation(..),
+ Addr::Str(s),
+ ) if !self.flags.double_quotes.is_atom() => {
+ if let &HeapCellValue::NamedStr(a1, ref n1, _) = &self.heap[s] {
+ if a1 != 2 || n1.as_str() != "." {
+ return Some(a1.cmp(&2).then_with(|| n1.as_str().cmp(".")));
+ }
+ } else {
+ unreachable!()
+ }
+ }
+ (
+ Addr::Str(s),
+ Addr::PStrLocation(..),
+ ) if !self.flags.double_quotes.is_atom() => {
+ if let &HeapCellValue::NamedStr(a1, ref n1, _) = &self.heap[s] {
+ if a1 != 2 || n1.as_str() != "." {
+ return Some(2.cmp(&a1).then_with(|| ".".cmp(n1.as_str())));
+ }
+ } else {
+ unreachable!()
+ }
+ }
+ _ => {
+ return None;
+ }
}
}
- (HeapCellValue::NamedStr(..), _) => {
- return Ordering::Greater;
- }
- (HeapCellValue::Addr(Addr::Lis(_)), _) => {
- return Ordering::Greater;
+ None => {
+ return None;
}
- _ => {}
}
}
- iter.first_to_expire
+ Some(iter.first_to_expire)
}
pub(super) fn reset_block(&mut self, addr: Addr) {
match self.store(addr) {
- Addr::Con(Constant::Usize(b)) => self.block = b,
+ Addr::Usize(b) => self.block = b,
_ => self.fail = true,
};
}
let d = self.store(self.deref(self[r1].clone()));
match d {
- Addr::Con(Constant::Atom(..)) | Addr::Con(Constant::Char(_)) => self.p += 1,
- Addr::Con(Constant::EmptyList) => self.p += 1,
+ Addr::Con(h) =>
+ if let HeapCellValue::Atom(..) = &self.heap[h] {
+ self.p += 1;
+ } else {
+ self.fail = true;
+ },
+ Addr::Char(_) => self.p += 1,
+ Addr::EmptyList => self.p += 1,
_ => self.fail = true,
};
}
let d = self.store(self.deref(self[r1].clone()));
match d {
- Addr::Con(Constant::Integer(_)) => self.p += 1,
- Addr::Con(Constant::CharCode(_)) => self.p += 1,
- Addr::Con(Constant::Char(_))
- if self.flags.double_quotes.is_codes() => self.p += 1,
- Addr::Con(Constant::Rational(r)) => {
- if r.denom() == &1 {
- self.p += 1;
- } else {
- self.fail = true;
+ Addr::Con(h) => {
+ match &self.heap[h] {
+ HeapCellValue::Integer(_) => {
+ self.p += 1;
+ }
+ HeapCellValue::Rational(ref r) => {
+ if r.denom() == &1 {
+ self.p += 1;
+ } else {
+ self.fail = true;
+ }
+ }
+ _ => {
+ self.fail = true;
+ }
}
}
- _ => self.fail = true,
+ Addr::CharCode(_) => {
+ 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].clone()));
+ let d = self.store(self.deref(self[r1]));
match d {
Addr::Str(_) | Addr::Lis(_) | Addr::PStrLocation(..) => self.p += 1,
let d = self.store(self.deref(self[r1].clone()));
match d {
- Addr::Con(Constant::Float(_)) => self.p += 1,
+ Addr::Float(_) => self.p += 1,
_ => self.fail = true,
};
}
let d = self.store(self.deref(self[r1].clone()));
match d {
- Addr::Con(Constant::Rational(_)) => self.p += 1,
- _ => self.fail = true,
+ Addr::Con(h) => {
+ if let HeapCellValue::Rational(_) = &self.heap[h] {
+ self.p += 1;
+ } else {
+ self.fail = true;
+ }
+ }
+ _ => {
+ self.fail = true;
+ }
};
}
&InlinedClauseType::IsString(r1) => {
let d = self.store(self.deref(self[r1].clone()));
match d {
- Addr::Con(Constant::String(..)) => self.p += 1,
+ Addr::PStrLocation(..) => self.p += 1,
_ => self.fail = true,
};
}
}
}
- fn try_functor_unify_components(&mut self, name: Addr, arity: Addr) {
- let a2 = self[temp_v!(2)].clone();
- let a3 = self[temp_v!(3)].clone();
-
- self.unify(a2, name);
-
- if !self.fail {
- self.unify(a3, arity);
- }
- }
-
fn try_functor_compound_case(
&mut self,
name: ClauseName,
arity: usize,
spec: Option<SharedOpDesc>,
) {
- let name = Addr::Con(Constant::Atom(name, spec));
- let arity = Addr::Con(Constant::Integer(Integer::from(arity)));
-
+ let name = self.heap.to_unifiable(HeapCellValue::Atom(name, spec));
self.try_functor_unify_components(name, arity);
}
+ fn try_functor_unify_components(
+ &mut self,
+ name: Addr,
+ arity: usize,
+ ) {
+ let a2 = self[temp_v!(2)];
+ let a3 = self[temp_v!(3)];
+
+ self.unify(a2, name);
+
+ if !self.fail {
+ self.unify(a3, Addr::Usize(arity));
+ }
+ }
+
fn try_functor_fabricate_struct(
&mut self,
name: ClauseName,
let f_a = if name.as_str() == "." && arity == 2 {
Addr::Lis(self.heap.h())
} else {
- let h = self.heap.h();
- self.heap.push(HeapCellValue::NamedStr(arity as usize, name, spec));
-
- Addr::Str(h)
+ self.heap.to_unifiable(HeapCellValue::NamedStr(arity as usize, name, spec))
};
for _ in 0..arity {
self.bind(r, f_a);
}
- pub(super) fn try_functor(&mut self, indices: &IndexStore) -> CallResult {
+ pub(super)
+ fn try_functor(&mut self, indices: &IndexStore) -> CallResult {
let stub = MachineError::functor_stub(clause_name!("functor"), 3);
- let a1 = self.store(self.deref(self[temp_v!(1)].clone()));
+ let a1 = self.store(self.deref(self[temp_v!(1)]));
- match a1.clone() {
- Addr::Stream(_) | Addr::DBRef(_) => self.fail = true,
- Addr::Con(Constant::String(n, ref s))
- if !self.flags.double_quotes.is_atom() && !s[n ..].is_empty() =>
- {
- let shared_op_desc = fetch_op_spec(clause_name!("."), 2, None, &indices.op_dir);
- self.try_functor_compound_case(clause_name!("."), 2, shared_op_desc)
- }
- Addr::Con(_) => self
- .try_functor_unify_components(a1, Addr::Con(Constant::Integer(Integer::from(0)))),
- Addr::Str(o) => match self.heap[o].clone() {
+ match a1 {
+ Addr::Stream(_) => {
+ self.fail = true;
+ }
+ Addr::Char(_) | Addr::CharCode(_) | Addr::Con(_) | Addr::Float(_) => {
+ self.try_functor_unify_components(a1, 0);
+ }
+ Addr::Str(o) => match self.heap.clone(o) {
HeapCellValue::NamedStr(arity, name, spec) => {
let spec = fetch_op_spec(name.clone(), arity, spec, &indices.op_dir);
self.try_functor_compound_case(name, arity, spec)
}
- _ => self.fail = true,
+ _ => {
+ self.fail = true;
+ }
},
Addr::Lis(_) | Addr::PStrLocation(..) => {
- let shared_op_desc = fetch_op_spec(clause_name!("."), 2, None, &indices.op_dir);
- self.try_functor_compound_case(clause_name!("."), 2, shared_op_desc)
+ let spec = fetch_op_spec(clause_name!("."), 2, None, &indices.op_dir);
+ self.try_functor_compound_case(clause_name!("."), 2, spec)
}
Addr::AttrVar(..) | Addr::HeapCell(_) | Addr::StackCell(..) => {
- let name = self.store(self.deref(self[temp_v!(2)].clone()));
- let arity = self.store(self.deref(self[temp_v!(3)].clone()));
+ let name = self.store(self.deref(self[temp_v!(2)]));
+ let arity = self.store(self.deref(self[temp_v!(3)]));
if name.is_ref() || arity.is_ref() {
// 8.5.1.3 a) & 8.5.1.3 b)
return Err(self.error_form(MachineError::instantiation_error(), stub));
}
- if let Addr::Con(Constant::Integer(arity)) = arity {
+ if let Addr::Con(h) = arity {
+ let arity = if let HeapCellValue::Integer(ref n) = &self.heap[h] {
+ n.clone()
+ } else {
+ return Err(
+ self.error_form(
+ MachineError::type_error(
+ self.heap.h(),
+ ValidType::Integer,
+ arity,
+ ),
+ stub,
+ )
+ );
+ };
+
let arity = match arity.to_isize() {
Some(arity) => arity,
None => {
};
if arity > MAX_ARITY as isize {
- let rep_err = MachineError::representation_error(RepFlag::MaxArity);
// 8.5.1.3 f)
+ let rep_err = MachineError::representation_error(RepFlag::MaxArity);
return Err(self.error_form(rep_err, stub));
} else if arity < 0 {
// 8.5.1.3 g)
- let arity = Integer::from(arity);
+ let arity = Number::Integer(Rc::new(Integer::from(arity)));
let dom_err = MachineError::domain_error(
- DomainError::NotLessThanZero,
- Addr::Con(Constant::Integer(arity)),
+ DomainErrorType::NotLessThanZero,
+ arity,
);
+
return Err(self.error_form(dom_err, stub));
}
match name {
- Addr::Con(_) if arity == 0 => self.unify(a1, name),
- Addr::Con(Constant::Atom(name, spec)) => self.try_functor_fabricate_struct(
- name,
- arity,
- spec,
- &indices.op_dir,
- a1.as_var().unwrap(),
- ),
- Addr::Con(Constant::Char(c)) => {
- let name = clause_name!(c.to_string(), indices.atom_tbl);
+ Addr::Con(_) if arity == 0 => {
+ self.unify(a1, name);
+ }
+ Addr::Con(h) => {
+ if let HeapCellValue::Atom(name, spec) = self.heap.clone(h) {
+ self.try_functor_fabricate_struct(
+ name,
+ arity,
+ spec,
+ &indices.op_dir,
+ a1.as_var().unwrap(),
+ );
+ } else {
+ // 8.5.1.3 e)
+ return Err(self.error_form(
+ MachineError::type_error(
+ self.heap.h(),
+ ValidType::Atom,
+ name,
+ ),
+ stub,
+ ))
+ }
+ }
+ Addr::Char(c) => {
self.try_functor_fabricate_struct(
- name,
+ clause_name!(c.to_string(), indices.atom_tbl),
arity,
None,
&indices.op_dir,
a1.as_var().unwrap(),
);
}
- Addr::Con(_) => {
- return Err(self
- .error_form(MachineError::type_error(ValidType::Atom, name), stub))
- } // 8.5.1.3 e)
_ => {
return Err(self.error_form(
- MachineError::type_error(ValidType::Atomic, name),
+ MachineError::type_error(self.heap.h(), ValidType::Atomic, name),
stub,
- ))
+ ));
} // 8.5.1.3 c)
- };
+ }
} else if !arity.is_ref() {
// 8.5.1.3 d)
return Err(
- self.error_form(MachineError::type_error(ValidType::Integer, arity), stub)
+ self.error_form(
+ MachineError::type_error(
+ self.heap.h(),
+ ValidType::Integer,
+ arity,
+ ),
+ stub,
+ )
);
}
}
+ _ => {
+ self.fail = true;
+ }
};
Ok(())
pub(super) fn term_dedup(&self, list: &mut Vec<Addr>) {
let mut result = vec![];
- for a2 in list.iter().cloned() {
- if let Some(a1) = result.last().cloned() {
- if self.compare_term_test(&a1, &a2) == Ordering::Equal {
+ for a2 in list.iter() {
+ if let Some(a1) = result.last() {
+ if self.compare_term_test(&a1, &a2) == Some(Ordering::Equal) {
continue;
}
}
- result.push(a2);
+ result.push(*a2);
}
*list = result;
r: RegType,
caller: MachineStub,
) -> Result<Vec<Addr>, MachineStub> {
- let a1 = self.store(self.deref(self[r].clone()));
+ let a1 = self.store(self.deref(self[r]));
match a1.clone() {
Addr::Lis(l) => {
self.try_from_inner_list(vec![], l, caller, a1)
}
- Addr::Con(Constant::String(n, ref s))
- if !self.flags.double_quotes.is_atom() => {
- if s.len() > n {
- Ok(Vec::from_iter(s[n ..].chars().map(|c| {
- Addr::Con(Constant::Char(c))
- })))
- } else {
- Ok(vec![])
- }
- }
Addr::PStrLocation(h, n) => {
self.try_from_partial_string(vec![], h, n, caller, a1)
}
- Addr::HeapCell(_) | Addr::StackCell(..) => {
+ Addr::AttrVar(_) | Addr::HeapCell(_) | Addr::StackCell(..) => {
Err(self.error_form(MachineError::instantiation_error(), caller))
}
- Addr::Con(Constant::EmptyList) => {
+ Addr::EmptyList => {
Ok(vec![])
}
_ => {
- Err(self.error_form(MachineError::type_error(ValidType::List, a1), caller))
+ Err(self.error_form(
+ MachineError::type_error(self.heap.h(), ValidType::List, a1),
+ caller,
+ ))
}
}
}
result.push(self.heap[hcp].as_addr(hcp));
l = hcp + 1;
}
- Addr::Con(Constant::String(n, ref s))
- if !self.flags.double_quotes.is_atom() =>
- {
- result.push(Addr::Con(Constant::String(n, s.clone())));
- break;
- }
Addr::PStrLocation(h, n) => {
return self.try_from_partial_string(result, h, n, caller, a1);
}
- Addr::Con(Constant::EmptyList) => {
+ Addr::EmptyList => {
break;
}
- Addr::HeapCell(_) | Addr::StackCell(..) => {
+ Addr::AttrVar(_) | Addr::HeapCell(_) | Addr::StackCell(..) => {
return Err(self.error_form(
MachineError::instantiation_error(),
caller,
}
_ => {
return Err(self.error_form(
- MachineError::type_error(ValidType::List, a1),
+ MachineError::type_error(self.heap.h(), ValidType::List, a1),
caller,
))
}
},
_ => {
return Err(self.error_form(
- MachineError::type_error(ValidType::List, a1),
+ MachineError::type_error(self.heap.h(), ValidType::List, a1),
caller,
))
}
) -> Result<Vec<Addr>, MachineStub> {
loop {
if let HeapCellValue::PartialString(ref pstr) = &self.heap[h] {
- let s = pstr.block_as_str();
-
- chars.extend(s[n ..].chars().map(|c| Addr::Con(Constant::Char(c))));
+ chars.extend(pstr.range_from(n ..).map(Addr::Char));
let tail = self.heap[h + 1].as_addr(h + 1);
match self.store(self.deref(tail)) {
- Addr::Con(Constant::EmptyList) => {
- return Ok(chars);
- }
- Addr::Con(Constant::String(n, ref s))
- if !self.flags.double_quotes.is_atom() =>
- {
- chars.push(Addr::Con(Constant::String(n, s.clone())));
+ Addr::EmptyList => {
return Ok(chars);
}
Addr::Lis(l) => {
}
_ => {
return Err(self.error_form(
- MachineError::type_error(ValidType::List, a1),
+ MachineError::type_error(self.heap.h(), ValidType::List, a1),
caller,
))
}
Addr::HeapCell(_) | Addr::StackCell(..) => {
Err(self.error_form(MachineError::instantiation_error(), stub))
}
- Addr::Str(s) => match self.heap[s].clone() {
- HeapCellValue::NamedStr(2, ref name, Some(_)) if *name == clause_name!("-") => {
- Ok(Addr::HeapCell(s + 1))
+ Addr::Str(s) => {
+ match self.heap.clone(s) {
+ HeapCellValue::NamedStr(2, ref name, Some(_))
+ if *name == clause_name!("-") => {
+ Ok(Addr::HeapCell(s + 1))
+ }
+ _ => {
+ Err(self.error_form(
+ MachineError::type_error(
+ self.heap.h(),
+ ValidType::Pair,
+ self.heap[s].as_addr(s),
+ ),
+ stub,
+ ))
+ }
}
- _ => Err(self.error_form(
- MachineError::type_error(ValidType::Pair, self.heap[s].as_addr(s)),
+ }
+ a => {
+ Err(self.error_form(
+ MachineError::type_error(
+ self.heap.h(),
+ ValidType::Pair,
+ a,
+ ),
stub,
- )),
- },
- a => Err(self.error_form(MachineError::type_error(ValidType::Pair, a), stub)),
+ ))
+ }
}
}
let a2 = self[temp_v!(2)].clone();
copy_term(CopyTerm::new(self), a1, attr_var_policy);
+
self.unify(Addr::HeapCell(old_h), a2);
}
// returns true on failure.
pub(super) fn structural_eq_test(&self) -> bool {
- let a1 = self[temp_v!(1)].clone();
- let a2 = self[temp_v!(2)].clone();
+ let a1 = self[temp_v!(1)];
+ let a2 = self[temp_v!(2)];
let mut var_pairs = IndexMap::new();
let iter = self.zipped_acyclic_pre_order_iter(a1, a2);
for (v1, v2) in iter {
- match (v1, v2) {
+ match (
+ self.heap.index_addr(&v1).as_ref(),
+ self.heap.index_addr(&v2).as_ref(),
+ ) {
(
HeapCellValue::Addr(Addr::Lis(_)),
- HeapCellValue::Addr(Addr::Con(Constant::String(..))),
+ HeapCellValue::Addr(Addr::PStrLocation(..)),
)
| (
- HeapCellValue::Addr(Addr::Con(Constant::String(..))),
+ HeapCellValue::Addr(Addr::PStrLocation(..)),
HeapCellValue::Addr(Addr::Lis(_)),
) if !self.flags.double_quotes.is_atom() => {
- continue;
}
(
- HeapCellValue::Addr(Addr::Con(Constant::String(n, ref s))),
- HeapCellValue::Addr(Addr::Con(Constant::EmptyList)),
- )
- | (
- HeapCellValue::Addr(Addr::Con(Constant::EmptyList)),
- HeapCellValue::Addr(Addr::Con(Constant::String(n, ref s))),
- ) if !self.flags.double_quotes.is_atom() => {
- if !s[n ..].is_empty() {
- return true;
- }
- }
- (HeapCellValue::NamedStr(ar1, n1, _), HeapCellValue::NamedStr(ar2, n2, _)) => {
+ HeapCellValue::NamedStr(ar1, n1, _),
+ HeapCellValue::NamedStr(ar2, n2, _),
+ ) => {
if ar1 != ar2 || n1 != n2 {
return true;
}
}
- (HeapCellValue::Addr(Addr::Lis(_)), HeapCellValue::Addr(Addr::Lis(_))) => {
- continue;
+ (
+ HeapCellValue::Addr(Addr::Lis(_)),
+ HeapCellValue::Addr(Addr::Lis(_)),
+ ) => {
}
(
- HeapCellValue::Addr(v1 @ Addr::HeapCell(_)),
- HeapCellValue::Addr(v2 @ Addr::AttrVar(_)),
+ &HeapCellValue::Addr(v1 @ Addr::HeapCell(_)),
+ &HeapCellValue::Addr(v2 @ Addr::AttrVar(_)),
)
| (
- HeapCellValue::Addr(v1 @ Addr::StackCell(..)),
- HeapCellValue::Addr(v2 @ Addr::AttrVar(_)),
+ &HeapCellValue::Addr(v1 @ Addr::StackCell(..)),
+ &HeapCellValue::Addr(v2 @ Addr::AttrVar(_)),
)
| (
- HeapCellValue::Addr(v1 @ Addr::AttrVar(_)),
- HeapCellValue::Addr(v2 @ Addr::AttrVar(_)),
+ &HeapCellValue::Addr(v1 @ Addr::AttrVar(_)),
+ &HeapCellValue::Addr(v2 @ Addr::AttrVar(_)),
)
| (
- HeapCellValue::Addr(v1 @ Addr::AttrVar(_)),
- HeapCellValue::Addr(v2 @ Addr::HeapCell(_)),
+ &HeapCellValue::Addr(v1 @ Addr::AttrVar(_)),
+ &HeapCellValue::Addr(v2 @ Addr::HeapCell(_)),
)
| (
- HeapCellValue::Addr(v1 @ Addr::AttrVar(_)),
- HeapCellValue::Addr(v2 @ Addr::StackCell(..)),
+ &HeapCellValue::Addr(v1 @ Addr::AttrVar(_)),
+ &HeapCellValue::Addr(v2 @ Addr::StackCell(..)),
)
| (
- HeapCellValue::Addr(v1 @ Addr::HeapCell(_)),
- HeapCellValue::Addr(v2 @ Addr::HeapCell(_)),
+ &HeapCellValue::Addr(v1 @ Addr::HeapCell(_)),
+ &HeapCellValue::Addr(v2 @ Addr::HeapCell(_)),
)
| (
- HeapCellValue::Addr(v1 @ Addr::HeapCell(_)),
- HeapCellValue::Addr(v2 @ Addr::StackCell(..)),
+ &HeapCellValue::Addr(v1 @ Addr::HeapCell(_)),
+ &HeapCellValue::Addr(v2 @ Addr::StackCell(..)),
)
| (
- HeapCellValue::Addr(v1 @ Addr::StackCell(..)),
- HeapCellValue::Addr(v2 @ Addr::StackCell(..)),
+ &HeapCellValue::Addr(v1 @ Addr::StackCell(..)),
+ &HeapCellValue::Addr(v2 @ Addr::StackCell(..)),
)
| (
- HeapCellValue::Addr(v1 @ Addr::StackCell(..)),
- HeapCellValue::Addr(v2 @ Addr::HeapCell(_)),
+ &HeapCellValue::Addr(v1 @ Addr::StackCell(..)),
+ &HeapCellValue::Addr(v2 @ Addr::HeapCell(_)),
) =>
- match (var_pairs.get(&v1).cloned(), var_pairs.get(&v2).cloned()) {
- (Some(ref v2_p), Some(ref v1_p)) if *v1_p == v1 && *v2_p == v2 => continue,
- (Some(_), _) | (_, Some(_)) => return true,
+ match (var_pairs.get(&v1), var_pairs.get(&v2)) {
+ (Some(ref v2_p), Some(ref v1_p)) if **v1_p == v1 && **v2_p == v2 => {
+ continue;
+ }
+ (Some(_), _) | (_, Some(_)) => {
+ return true;
+ }
(None, None) => {
- var_pairs.insert(v1.clone(), v2.clone());
+ var_pairs.insert(v1, v2);
var_pairs.insert(v2, v1);
}
},
- (HeapCellValue::Addr(a1), HeapCellValue::Addr(a2)) => {
+ (
+ HeapCellValue::PartialString(ref pstr1),
+ HeapCellValue::PartialString(ref pstr2),
+ ) => {
+ let pstr1_iter = pstr1.range_from(0 ..);
+ let pstr2_iter = pstr2.range_from(0 ..);
+
+ for (c1, c2) in pstr1_iter.zip(pstr2_iter) {
+ if c1 != c2 {
+ return true;
+ }
+ }
+ }
+ (
+ HeapCellValue::Addr(Addr::PStrLocation(..)),
+ HeapCellValue::Addr(Addr::PStrLocation(..)),
+ ) => {
+ }
+ (
+ HeapCellValue::Integer(n1),
+ HeapCellValue::Integer(n2),
+ ) => {
+ if &*n1 != &*n2 {
+ return true;
+ }
+ }
+ (
+ HeapCellValue::Rational(n1),
+ HeapCellValue::Rational(n2),
+ ) => {
+ if &*n1 != &*n2 {
+ return true;
+ }
+ }
+ (
+ HeapCellValue::Integer(ref n1),
+ HeapCellValue::Rational(ref n2),
+ ) |
+ (
+ HeapCellValue::Rational(ref n2),
+ HeapCellValue::Integer(ref n1),
+ ) => {
+ if n1.as_ref().partial_cmp(&**n2) == Some(Ordering::Equal) {
+ return true;
+ }
+ }
+ (
+ HeapCellValue::Atom(ref n1, ref spec_1),
+ HeapCellValue::Atom(ref n2, ref spec_2),
+ ) => {
+ if n1 != n2 || spec_1 != spec_2 {
+ return true;
+ }
+ }
+ (
+ HeapCellValue::DBRef(ref db_ref_1),
+ HeapCellValue::DBRef(ref db_ref_2),
+ ) => {
+ if db_ref_1 != db_ref_2 {
+ return true;
+ }
+ }
+ (
+ HeapCellValue::Addr(a1),
+ HeapCellValue::Addr(a2),
+ ) => {
if a1 != a2 {
return true;
}
}
- _ => return true,
+ _ => {
+ return true;
+ }
}
}
for v in self.acyclic_pre_order_iter(a) {
match v {
- HeapCellValue::Addr(Addr::HeapCell(..)) => return true,
- HeapCellValue::Addr(Addr::StackCell(..)) => return true,
- HeapCellValue::Addr(Addr::AttrVar(..)) => return true,
+ Addr::HeapCell(..) => return true,
+ Addr::StackCell(..) => return true,
+ Addr::AttrVar(..) => return true,
_ => {}
}
}
&CutInstruction::GetLevel(r) => {
let b0 = self.b0;
- self[r] = Addr::Con(Constant::CutPoint(b0));
+ self[r] = Addr::CutPoint(b0);
self.p += 1;
}
&CutInstruction::GetLevelAndUnify(r) => {
pub mod machine_indices;
pub(super) mod machine_state;
pub mod modules;
-mod partial_string;
+pub mod partial_string;
mod raw_block;
mod stack;
pub(crate) mod streams;
pub(super) mod term_expansion;
pub mod toplevel;
+#[macro_use]
+mod arithmetic_ops;
#[macro_use]
mod machine_state_impl;
mod system_calls;
// the first of these is the path to the scryer-prolog executable, so skip
// it.
for filename in env::args().skip(1) {
- let atom = atom!(filename, self.indices.atom_tbl);
- filename_atoms.push(Addr::Con(atom));
+ let atom = clause_name!(filename, self.indices.atom_tbl);
+ filename_atoms.push(HeapCellValue::Atom(atom, None));
}
let list_addr =
HeapCellValue::NamedStr(arity, ref name, _)
if *arity == 2 && name.as_str() == "/" => {
let name = match &self.machine_st.heap[s+1] {
- &HeapCellValue::Addr(Addr::Con(Constant::Atom(ref name, _))) =>
+ &HeapCellValue::Atom(ref name, _) =>
name.clone(),
_ =>
unreachable!()
};
let arity = match &self.machine_st.heap[s+2] {
- &HeapCellValue::Addr(Addr::Con(Constant::Integer(ref arity))) =>
+ &HeapCellValue::Integer(ref arity) =>
arity.to_usize().unwrap(),
_ =>
unreachable!()
HeapCellValue::NamedStr(arity, ref name, _)
if *arity == 3 && name.as_str() == "op" => {
let name = match &self.machine_st.heap[s+3] {
- &HeapCellValue::Addr(Addr::Con(Constant::Atom(ref name, _))) =>
+ &HeapCellValue::Atom(ref name, _) =>
name.clone(),
_ =>
unreachable!()
};
let spec = match &self.machine_st.heap[s+2] {
- &HeapCellValue::Addr(Addr::Con(Constant::Atom(ref name, _))) =>
+ &HeapCellValue::Atom(ref name, _) =>
name.clone(),
_ =>
unreachable!()
};
let prec = match &self.machine_st.heap[s+1] {
- &HeapCellValue::Addr(Addr::Con(Constant::Integer(ref arity))) =>
+ &HeapCellValue::Integer(ref arity) =>
arity.to_usize().unwrap(),
_ =>
unreachable!()
let cached_query = mem::replace(&mut self.code_repo.cached_query, vec![]);
let module_spec = self.machine_st[temp_v!(1)].clone();
- let name = match self.machine_st.store(self.machine_st.deref(module_spec)) {
- Addr::Con(Constant::Atom(name, _)) => name,
- _ => unreachable!()
+ 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!(),
+ }
};
let load_result = match to_src(name) {
let cached_query = mem::replace(&mut self.code_repo.cached_query, vec![]);
let module_spec = self.machine_st[temp_v!(1)].clone();
- let name = match self.machine_st.store(self.machine_st.deref(module_spec)) {
- Addr::Con(Constant::Atom(name, _)) => name,
- _ => unreachable!()
+ 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!(),
+ }
};
let exports = match self.extract_module_export_list() {
-use crate::prolog::machine::raw_block::*;
-
+use std::alloc;
use std::mem;
use std::ptr;
-use std::slice;
+use std::ops::{Range, RangeFrom};
use std::str;
-pub(crate) struct PartialStringTraits {}
-
-impl RawBlockTraits for PartialStringTraits {
- #[inline]
- fn init_size() -> usize {
- 0
- }
-
- #[inline]
- fn align() -> usize {
- mem::align_of::<char>()
- }
-}
-
pub struct PartialString {
- pub(super) buf: RawBlock<PartialStringTraits>,
+ buf: *const u8,
}
impl Clone for PartialString {
}
}
-impl PartialEq for PartialString {
- #[inline]
- fn eq(&self, other: &Self) -> bool {
- self as *const _ == other as *const _
- }
-}
-
-fn scan_for_terminator(src: &str) -> usize {
+fn scan_for_terminator<Iter: Iterator<Item = char>>(iter: Iter) -> usize {
let mut terminator_idx = 0;
- for c in src.chars() {
+ for c in iter {
if c == '\u{0}' {
break;
}
terminator_idx
}
+pub struct PStrIter {
+ buf: *const u8,
+}
+
+impl PStrIter {
+ #[inline]
+ fn from(buf: *const u8, idx: usize) -> Self {
+ PStrIter {
+ buf: (buf as usize + idx) as *const _
+ }
+ }
+}
+
+impl Iterator for PStrIter {
+ type Item = char;
+
+ fn next(&mut self) -> Option<Self::Item> {
+ unsafe {
+ let b = ptr::read(self.buf);
+
+ if b == 0u8 {
+ return None;
+ }
+
+ let c = ptr::read(self.buf as *const char);
+ self.buf = self.buf.offset(c.len_utf8() as isize);
+
+ Some(c)
+ }
+ }
+}
+
+pub struct PStrIterBounded {
+ buf: *const u8,
+ end: *const u8,
+}
+
+impl PStrIterBounded {
+ #[inline]
+ fn from(buf: *const u8, start: usize, end: usize) -> Self {
+ PStrIterBounded {
+ buf: (buf as usize + start) as *const _,
+ end: (buf as usize + end) as *const _,
+ }
+ }
+}
+
+impl Iterator for PStrIterBounded {
+ type Item = char;
+
+ fn next(&mut self) -> Option<Self::Item> {
+ unsafe {
+ if self.buf >= self.end {
+ return None;
+ }
+
+ let b = ptr::read(self.buf);
+
+ if b == 0u8 {
+ return None;
+ }
+
+ let c = ptr::read(self.buf as *const char);
+ self.buf = self.buf.offset(c.len_utf8() as isize);
+
+ Some(c)
+ }
+ }
+}
+
impl PartialString {
+ #[inline]
pub(super)
fn new(src: &str) -> Option<(Self, &str)> {
let pstr = PartialString {
- buf: RawBlock::with_capacity(src.len() + '\u{0}'.len_utf8()),
+ buf: ptr::null_mut(),
};
unsafe {
}
}
+ #[inline]
+ pub(super)
+ fn empty() -> Self {
+ PartialString {
+ buf: "\u{0}".as_bytes()[0] as *const _,
+ }
+ }
+
unsafe fn append_chars(mut self, src: &str) -> Option<(Self, &str)> {
- let terminator_idx = scan_for_terminator(src);
+ let terminator_idx = scan_for_terminator(src.chars());
if terminator_idx == 0 {
return None;
}
- let new_top = self.buf.new_block(terminator_idx + '\u{0}'.len_utf8());
+ let layout = alloc::Layout::from_size_align_unchecked(
+ src.len() + '\u{0}'.len_utf8(),
+ mem::align_of::<u8>(),
+ );
+
+ self.buf = alloc::alloc(layout) as *const _;
ptr::copy(
src.as_ptr(),
- self.buf.top as *mut _,
+ self.buf as *mut _,
terminator_idx,
);
- self.buf.top = (new_top as usize - '\u{0}'.len_utf8()) as *const _;
self.write_terminator_at(terminator_idx);
Some(if terminator_idx != src.len() {
})
}
+ #[inline]
+ pub(crate)
+ fn iter(&self) -> PStrIter {
+ PStrIter {
+ buf: self.buf,
+ }
+ }
+
pub(super)
fn clone_from_offset(&self, n: usize) -> Self {
let mut pstr = PartialString {
- buf: RawBlock::with_capacity(self.len() + '\u{0}'.len_utf8()),
+ buf: ptr::null_mut(),
};
unsafe {
- let len = if self.len() > n { self.len() - n } else { 0 };
- let new_top = pstr.buf.new_block(len + '\u{0}'.len_utf8());
+ let len = scan_for_terminator(self.range_from(0 ..));
+ let len = if len > n { len - n } else { 0 };
+
+ let layout = alloc::Layout::from_size_align_unchecked(
+ len + '\u{0}'.len_utf8(),
+ mem::align_of::<u8>(),
+ );
+
+ pstr.buf = alloc::alloc(layout);
if len > 0 {
ptr::copy(
- (self.buf.base as usize + n) as *mut u8,
- pstr.buf.base as *mut _,
+ (self.buf as usize + n) as *const u8,
+ pstr.buf as *mut _,
len,
);
}
pstr.write_terminator_at(len);
- pstr.buf.top = (new_top as usize - '\u{0}'.len_utf8()) as *const _;
}
pstr
fn write_terminator_at(&mut self, index: usize) {
unsafe {
ptr::write(
- (self.buf.base as usize + index) as *mut u8,
+ (self.buf as usize + index) as *mut u8,
0u8,
);
}
}
#[inline]
- pub(crate)
- fn block_as_str(&self) -> &str {
- unsafe {
- let slice = slice::from_raw_parts(self.buf.base, self.len());
- str::from_utf8(slice).unwrap()
- }
+ pub fn range(&self, index: Range<usize>) -> PStrIterBounded {
+ PStrIterBounded::from(self.buf, index.start, index.end)
}
#[inline]
- pub fn len(&self) -> usize {
- self.buf.top as usize - self.buf.base as usize
+ pub fn range_from(&self, index: RangeFrom<usize>) -> PStrIter {
+ PStrIter::from(self.buf, index.start)
+ }
+
+ #[inline]
+ pub fn at_end(&self, end_n: usize) -> bool {
+ unsafe {
+ ptr::read((self.buf as usize + end_n) as *const u8) == 0u8
+ }
}
}
pub enum StreamInstance {
Bytes(Cursor<Vec<u8>>),
DynReadSource(Box<dyn Read>),
- File(File),
+ File(File),
+ Null,
ReadlineStream(ReadlineStream),
Stdin,
Stdout,
}
}
+ #[inline]
+ pub(crate)
+ fn null_stream() -> Self {
+ Stream {
+ options: StreamOptions::default(), // TODO: null_options?
+ stream_inst: WrappedStreamInstance::new(
+ StreamInstance::Null
+ ),
+ }
+ }
+
#[inline]
pub(crate)
fn is_stdout(&self) -> bool {
match *self.stream_inst.0.borrow() {
StreamInstance::Stdin
| StreamInstance::TcpStream(_)
- | StreamInstance::Bytes(_)
+ | StreamInstance::Bytes(_)
| StreamInstance::ReadlineStream(_)
| StreamInstance::DynReadSource(_)
| StreamInstance::File(_) => {
match *self.stream_inst.0.borrow() {
StreamInstance::Stdout
| StreamInstance::TcpStream(_)
- | StreamInstance::Bytes(_)
+ | StreamInstance::Bytes(_)
| StreamInstance::File(_) => {
true
}
StreamInstance::Stdin => {
stdin().read(buf)
}
- StreamInstance::Stdout => {
+ StreamInstance::Stdout | StreamInstance::Null => {
Err(std::io::Error::new(
ErrorKind::PermissionDenied,
StreamError::ReadFromOutputStream,
use indexmap::{IndexMap, IndexSet};
+use std::cmp;
use std::io::{stdout, Write};
use std::iter::once;
use std::mem;
Addr::PStrLocation(h, n) => {
CycleSearchResult::PStrLocation(self.steps, h, n)
}
- Addr::Con(Constant::EmptyList) => {
+ Addr::EmptyList => {
CycleSearchResult::ProperList(self.steps)
}
_ => {
impl MachineState {
// a step in Brent's algorithm.
fn brents_alg_step(&self, brent_st: &mut BrentAlgState) -> Option<CycleSearchResult> {
- match self.store(self.deref(brent_st.hare.clone())) {
- Addr::Con(Constant::EmptyList) => {
+ match self.store(self.deref(brent_st.hare)) {
+ Addr::EmptyList => {
Some(CycleSearchResult::ProperList(brent_st.steps))
}
addr @ Addr::HeapCell(_) | addr @ Addr::StackCell(..) | addr @ Addr::AttrVar(_) => {
addr.as_var().unwrap(),
))
}
- Addr::Con(Constant::String(n, s)) if !self.flags.double_quotes.is_atom() => {
- if let Some(c) = s.chars().next() {
- brent_st.step(Addr::Con(Constant::String(n + c.len_utf8(), s)))
- } else {
- Some(CycleSearchResult::CompleteString(s.len(), s))
- }
- }
Addr::PStrLocation(h, n) => {
match &self.heap[h] {
HeapCellValue::PartialString(ref pstr) => {
- let s = pstr.block_as_str();
-
- if let Some(c) = s[n ..].chars().next() {
+ if let Some(c) = pstr.range_from(n ..).next() {
brent_st.step(Addr::PStrLocation(h, n + c.len_utf8()))
} else {
unreachable!()
Addr::PStrLocation(h, _) => {
return CycleSearchResult::UntouchedList(h);
}
- Addr::Con(Constant::EmptyList) => {
+ Addr::EmptyList => {
return CycleSearchResult::EmptyList;
}
- Addr::Con(Constant::String(0, ref s))
- if max_steps > 0 && !self.flags.double_quotes.is_atom() => {
- if max_steps >= s.len() {
- return CycleSearchResult::CompleteString(s.len(), s.clone());
+ Addr::Con(h) if max_steps > 0 => {
+ if let HeapCellValue::PartialString(_) = &self.heap[h] {
+ if !self.flags.double_quotes.is_atom() {
+ Addr::PStrLocation(h, 0)
} else {
- return CycleSearchResult::UntouchedString(max_steps, s.clone());
+ return CycleSearchResult::NotList;
}
+ } else {
+ return CycleSearchResult::NotList;
}
- Addr::Con(Constant::String(0, ref s))
- if !self.flags.double_quotes.is_atom() => {
- return CycleSearchResult::UntouchedString(0, s.clone());
- }
- Addr::Con(Constant::String(n, ref s))
- if max_steps > 0 && !self.flags.double_quotes.is_atom() => {
- if max_steps >= s.len() - n {
- let s = Rc::new(String::from(&s[n ..]));
- return CycleSearchResult::CompleteString(s.len(), s);
- } else {
- return CycleSearchResult::UntouchedString(max_steps, s.clone());
+ }
+ Addr::Con(h) => {
+ if let HeapCellValue::PartialString(_) = &self.heap[h] {
+ if !self.flags.double_quotes.is_atom() {
+ return CycleSearchResult::UntouchedList(h);
}
}
- Addr::Con(Constant::String(n, ref s))
- if !self.flags.double_quotes.is_atom() => {
- return CycleSearchResult::UntouchedString(n, s.clone());
- }
+
+ return CycleSearchResult::NotList;
+ }
_ => {
return CycleSearchResult::NotList;
}
Addr::Lis(offset) => {
Addr::Lis(offset)
}
- Addr::Con(Constant::EmptyList) => {
+ Addr::EmptyList => {
return CycleSearchResult::EmptyList;
}
Addr::PStrLocation(h, n) => {
Addr::PStrLocation(h, n)
}
- Addr::Con(Constant::String(0, ref s)) if !self.flags.double_quotes.is_atom() => {
- return CycleSearchResult::CompleteString(s.len(), s.clone());
- }
- Addr::Con(Constant::String(n, ref s)) if !self.flags.double_quotes.is_atom() => {
- let s = Rc::new(String::from(&s[n ..]));
- return CycleSearchResult::CompleteString(s.len(), s);
+ Addr::Con(h) => {
+ if let HeapCellValue::PartialString(_) = &self.heap[h] {
+ if !self.flags.double_quotes.is_atom() {
+ Addr::PStrLocation(h, 0)
+ } else {
+ return CycleSearchResult::NotList;
+ }
+ } else {
+ return CycleSearchResult::NotList;
+ }
}
_ => {
return CycleSearchResult::NotList;
}
fn finalize_skip_max_list(&mut self, n: usize, addr: Addr) {
- let target_n = self[temp_v!(1)].clone();
- self.unify(Addr::Con(Constant::Integer(Integer::from(n))), target_n);
+ let target_n = self[temp_v!(1)];
+ self.unify(Addr::Usize(n), target_n);
if !self.fail {
- let xs = self[temp_v!(4)].clone();
+ let xs = self[temp_v!(4)];
self.unify(addr, xs);
}
}
- pub(super) fn skip_max_list(&mut self) -> CallResult {
- let max_steps = self.store(self.deref(self[temp_v!(2)].clone()));
+ fn skip_max_list_result(&mut self, max_steps: &Integer) {
+ let search_result =
+ if let Some(max_steps) = max_steps.to_isize() {
+ if max_steps == -1 {
+ self.detect_cycles(self[temp_v!(3)])
+ } else {
+ self.detect_cycles_with_max(
+ max_steps as usize,
+ self[temp_v!(3)],
+ )
+ }
+ } else {
+ self.detect_cycles(self[temp_v!(3)])
+ };
- match max_steps {
- Addr::Con(Constant::Integer(ref max_steps)) => {
- if max_steps.to_isize().map(|i| i >= -1).unwrap_or(false) {
- let n = self.store(self.deref(self[temp_v!(1)].clone()));
+ match search_result {
+ CycleSearchResult::PStrLocation(steps, h, n) => {
+ self.finalize_skip_max_list(steps, Addr::PStrLocation(h, n));
+ }
+ CycleSearchResult::UntouchedList(l) => {
+ self.finalize_skip_max_list(0, Addr::Lis(l))
+ }
+ CycleSearchResult::EmptyList => {
+ self.finalize_skip_max_list(0, Addr::EmptyList)
+ }
+ CycleSearchResult::PartialList(n, r) => {
+ self.finalize_skip_max_list(n, r.as_addr())
+ }
+ CycleSearchResult::ProperList(steps) => {
+ self.finalize_skip_max_list(steps, Addr::EmptyList)
+ }
+ CycleSearchResult::NotList => {
+ let xs0 = self[temp_v!(3)];
+ self.finalize_skip_max_list(0, xs0);
+ }
+ };
+ }
- match n {
- Addr::Con(Constant::Integer(ref n)) if n == &0 => {
- let xs0 = self[temp_v!(3)].clone();
- let xs = self[temp_v!(4)].clone();
+ pub(super) fn skip_max_list(&mut self) -> CallResult {
+ let max_steps = self.store(self.deref(self[temp_v!(2)]));
- self.unify(xs0, xs);
- }
- _ => {
- let search_result =
- if let Some(max_steps) = max_steps.to_isize() {
- if max_steps == -1 {
- self.detect_cycles(self[temp_v!(3)].clone())
+ 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.detect_cycles_with_max(
- max_steps as usize,
- self[temp_v!(3)].clone(),
- )
+ self.skip_max_list_result(max_steps.as_ref());
}
} else {
- self.detect_cycles(self[temp_v!(3)].clone())
- };
-
- match search_result {
- CycleSearchResult::PStrLocation(steps, h, n) => {
- self.finalize_skip_max_list(steps, Addr::PStrLocation(h, n));
- }
- CycleSearchResult::CompleteString(n, _) => {
- self.finalize_skip_max_list(n, Addr::Con(Constant::EmptyList));
- }
- CycleSearchResult::UntouchedString(n, s) => {
- self.finalize_skip_max_list(0, Addr::Con(Constant::String(n, s)));
- }
- CycleSearchResult::UntouchedList(l) => {
- self.finalize_skip_max_list(0, Addr::Lis(l))
- }
- CycleSearchResult::EmptyList => {
- self.finalize_skip_max_list(0, Addr::Con(Constant::EmptyList))
- }
- CycleSearchResult::PartialList(n, r) => {
- self.finalize_skip_max_list(n, r.as_addr())
- }
- CycleSearchResult::ProperList(steps) => {
- self.finalize_skip_max_list(steps, Addr::Con(Constant::EmptyList))
- }
- CycleSearchResult::NotList => {
- let xs0 = self[temp_v!(3)].clone();
- self.finalize_skip_max_list(0, xs0);
+ unreachable!()
}
}
+ _ => {
+ self.skip_max_list_result(max_steps.as_ref());
+ }
}
+ } else {
+ self.fail = true;
}
} else {
- self.fail = true;
+ unreachable!()
}
}
Addr::HeapCell(_) | Addr::StackCell(..) => {
addr => {
let stub = MachineError::functor_stub(clause_name!("$skip_max_list"), 4);
return Err(
- self.error_form(MachineError::type_error(ValidType::Integer, addr), stub)
+ self.error_form(
+ MachineError::type_error(
+ self.heap.h(),
+ ValidType::Integer,
+ addr
+ ),
+ stub,
+ )
);
}
};
}
fn get_stream_or_alias(
- &self,
+ &mut self,
addr: Addr,
indices: &IndexStore,
caller: &'static str,
) -> Result<Stream, MachineStub>
{
Ok(match addr {
- Addr::Con(Constant::Atom(atom, op_spec)) => {
- match indices.stream_aliases.get(&atom) {
- Some(stream) => {
- stream.clone()
- }
- None => {
- let stub = MachineError::functor_stub(clause_name!(caller), 1);
- let addr = Addr::Con(Constant::Atom(atom, op_spec));
+ Addr::Con(h) if self.heap.atom_at(h) => {
+ if let HeapCellValue::Atom(ref atom, ref spec) = self.heap.clone(h) {
+ match indices.stream_aliases.get(atom) {
+ Some(stream) => {
+ stream.clone()
+ }
+ None => {
+ let stub = MachineError::functor_stub(clause_name!(caller), 1);
+ let h = self.heap.h();
- let h = self.heap.h();
-
- return Err(self.error_form(
- MachineError::existence_error(h, ExistenceError::Stream(addr)),
- stub,
- ));
+ let addr = self.heap.to_unifiable(
+ HeapCellValue::Atom(atom.clone(), spec.clone())
+ );
+
+ return Err(self.error_form(
+ MachineError::existence_error(h + 1, ExistenceError::Stream(addr)),
+ stub,
+ ));
+ }
}
+ } else {
+ unreachable!()
}
}
- Addr::Stream(stream) => {
- stream
+ Addr::Stream(h) => {
+ if let HeapCellValue::Stream(ref stream) = &self.heap[h] {
+ stream.clone()
+ } else {
+ unreachable!()
+ }
}
_ => {
let stub = MachineError::functor_stub(clause_name!(caller), 1);
-
+
return Err(self.error_form(
- MachineError::domain_error(DomainError::StreamOrAlias, addr),
+ MachineError::domain_error(DomainErrorType::StreamOrAlias, addr),
stub,
));
}
- })
+ })
}
- fn read_term(&mut self,
- current_input_stream: &mut Stream,
- indices: &mut IndexStore)
- -> CallResult
- {
+ fn read_term(
+ &mut self,
+ current_input_stream: &mut Stream,
+ indices: &mut IndexStore,
+ ) -> CallResult {
match self.read(
&mut parsing_stream(current_input_stream.clone()),
indices.atom_tbl.clone(),
for (var, binding) in term_write_result.var_dict.into_iter().rev() {
let var_atom = clause_name!(var.to_string(), indices.atom_tbl);
- let var_atom = Constant::Atom(var_atom, None);
let h = self.heap.h();
let spec = fetch_atom_op_spec(clause_name!("="), None, &indices.op_dir);
self.heap.push(HeapCellValue::NamedStr(2, clause_name!("="), spec));
- self.heap.push(HeapCellValue::Addr(Addr::Con(var_atom)));
+ self.heap.push(HeapCellValue::Atom(var_atom, None));
self.heap.push(HeapCellValue::Addr(binding));
list_of_var_eqs.push(Addr::Str(h));
let c = Constant::Usize(self.block);
let addr = self[r].clone();
- self.write_constant_to_var(addr, c);
+ self.write_constant_to_var(addr, &c);
self.block
}
AddrConstr: Fn(usize) -> Addr,
{
match self.store(self.deref(self[temp_v!(1)].clone())) {
- Addr::Con(Constant::Usize(lh_offset)) => {
+ Addr::Usize(lh_offset) => {
if lh_offset >= self.lifted_heap.h() {
self.lifted_heap.truncate(lh_offset);
} else {
let a2 = self[temp_v!(2)].clone();
if let Some(r) = a2.as_var() {
- let spec =
- get_clause_spec(name.clone(), *arity, composite_op!(&indices.op_dir));
- self.bind(r, Addr::DBRef(DBRef::NamedPred(name.clone(), *arity, spec)));
+ let spec = get_clause_spec(
+ name.clone(),
+ *arity,
+ composite_op!(&indices.op_dir),
+ );
+
+ let addr = self.heap.to_unifiable(HeapCellValue::DBRef(
+ DBRef::NamedPred(
+ name.clone(),
+ *arity,
+ spec,
+ )
+ ));
+
+ self.bind(r, addr);
+
return;
}
}
let a2 = self[temp_v!(2)].clone();
if let Some(r) = a2.as_var() {
- self.bind(
- r,
- Addr::DBRef(DBRef::Op(
- *priority,
- *spec,
- name.clone(),
- op_dir.clone(),
- SharedOpDesc::new(*priority, *spec),
- )),
+ let addr = self.heap.to_unifiable(
+ HeapCellValue::DBRef(
+ DBRef::Op(
+ *priority,
+ *spec,
+ name.clone(),
+ op_dir.clone(),
+ SharedOpDesc::new(*priority, *spec)
+ ),
+ ),
);
+
+ self.bind(r, addr);
} else {
self.fail = true;
}
}
fn int_to_char_code(
- &mut self,
+ &self,
n: &Integer,
stub: &'static str,
arity: usize,
return Err(self.error_form(err, stub));
}
Ok(Term::Constant(_, Constant::Rational(n))) => {
- self.unify(nx, Addr::Con(Constant::Rational(n)))
+ let addr = self.heap.put_constant(Constant::Rational(n));
+ self.unify(nx, addr);
}
Ok(Term::Constant(_, Constant::Float(n))) => {
- self.unify(nx, Addr::Con(Constant::Float(n)))
+ let addr = self.heap.put_constant(Constant::Float(n));
+ self.unify(nx, addr);
}
Ok(Term::Constant(_, Constant::Integer(n))) => {
- self.unify(nx, Addr::Con(Constant::Integer(n)))
+ let addr = self.heap.put_constant(Constant::Integer(n));
+ self.unify(nx, addr);
}
Ok(Term::Constant(_, Constant::CharCode(c))) => {
- self.unify(nx, Addr::Con(Constant::CharCode(c)))
+ self.unify(nx, Addr::CharCode(c))
}
_ => {
let err = ParserError::ParseBigInt(0, 0);
}
fn fetch_attribute_goals(&mut self, mut attr_goals: Vec<Addr>) {
- attr_goals.sort_unstable_by(|a1, a2| self.compare_term_test(a1, a2));
+ attr_goals.sort_unstable_by(|a1, a2| {
+ self.compare_term_test(a1, a2)
+ .unwrap_or(cmp::Ordering::Less)
+ });
+
self.term_dedup(&mut attr_goals);
let attr_goals = Addr::HeapCell(self.heap.to_list(attr_goals.into_iter()));
// adjust cut point to occur after call_continuation.
if num_cells > 0 {
- if let Addr::Con(Constant::CutPoint(_)) = self.heap[s+2].as_addr(s+2) {
- and_frame[1] = Addr::Con(Constant::CutPoint(self.b));
+ if let Addr::CutPoint(_) = self.heap[s+2].as_addr(s+2) {
+ and_frame[1] = Addr::CutPoint(self.b);
} else {
and_frame[1] = self.heap[s+2].as_addr(s+2);
}
&SystemClauseType::BindFromRegister => {
let reg = self.store(self.deref(self[temp_v!(2)].clone()));
let n = match reg {
- Addr::Con(Constant::Integer(n)) => n.to_usize(),
+ Addr::Con(h) =>
+ if let HeapCellValue::Integer(ref n) = &self.heap[h] {
+ n.to_usize()
+ } else {
+ unreachable!()
+ }
_ => unreachable!()
};
return Ok(());
}
&SystemClauseType::CurrentInput => {
- let addr = self.store(self.deref(self[temp_v!(1)].clone()));
+ let addr = self.store(self.deref(self[temp_v!(1)]));
+
let stream = current_input_stream.clone();
match addr {
addr if addr.is_ref() => {
- self.unify(Addr::Stream(stream), addr);
+ let stream = self.heap.to_unifiable(HeapCellValue::Stream(stream));
+ self.unify(stream, addr);
}
Addr::Stream(other_stream) => {
- self.fail = stream != other_stream;
+ if let HeapCellValue::Stream(ref other_stream) = &self.heap[other_stream] {
+ self.fail = current_input_stream != other_stream;
+ } else {
+ unreachable!()
+ }
}
addr => {
let stub = MachineError::functor_stub(
);
let err = MachineError::domain_error(
- DomainError::Stream,
+ DomainErrorType::Stream,
addr,
);
match addr {
addr if addr.is_ref() => {
- self.unify(Addr::Stream(stream), addr);
+ let stream = self.heap.to_unifiable(HeapCellValue::Stream(stream));
+ self.unify(stream, addr);
}
Addr::Stream(other_stream) => {
- self.fail = stream != other_stream;
+ if let HeapCellValue::Stream(ref other_stream) = &self.heap[other_stream] {
+ self.fail = current_output_stream != other_stream;
+ } else {
+ unreachable!()
+ }
}
addr => {
let stub = MachineError::functor_stub(
);
let err = MachineError::domain_error(
- DomainError::Stream,
+ DomainErrorType::Stream,
addr,
);
let a1 = self[temp_v!(1)].clone();
match self.store(self.deref(a1)) {
- Addr::Con(Constant::Char(c)) => {
- let iter = once(Addr::Con(Constant::Char(c)));
+ Addr::Char(c) => {
+ let iter = once(Addr::Char(c));
let list_of_chars = Addr::HeapCell(self.heap.to_list(iter));
- let a2 = self[temp_v!(2)].clone();
+ let a2 = self[temp_v!(2)];
self.unify(a2, list_of_chars);
}
- Addr::Con(Constant::Atom(name, _)) => {
- let iter = name.as_str().chars().map(|c| Addr::Con(Constant::Char(c)));
- let list_of_chars = Addr::HeapCell(self.heap.to_list(iter));
+ Addr::Con(h) if self.heap.atom_at(h) => {
+ if let HeapCellValue::Atom(name, _) = self.heap.clone(h) {
+ let iter = name.as_str().chars().map(|c| Addr::Char(c));
+ let list_of_chars = Addr::HeapCell(self.heap.to_list(iter));
- let a2 = self[temp_v!(2)].clone();
+ let a2 = self[temp_v!(2)];
- match self.store(self.deref(a2)) {
- Addr::Con(Constant::String(..))
- if !self.flags.double_quotes.is_chars() => {
- self.fail = true;
+ match self.store(self.deref(a2)) {
+ Addr::PStrLocation(..)
+ if !self.flags.double_quotes.is_chars() => {
+ self.fail = true;
+ }
+ a2 => {
+ self.unify(a2, list_of_chars);
}
- a2 => {
- self.unify(a2, list_of_chars);
}
+ } else {
+ unreachable!()
}
}
- Addr::Con(Constant::EmptyList) => {
+ Addr::EmptyList => {
let a2 = self[temp_v!(2)].clone();
let chars = vec![
- Addr::Con(Constant::Char('[')),
- Addr::Con(Constant::Char(']')),
+ Addr::Char('['),
+ Addr::Char(']'),
];
- let list_of_chars = Addr::HeapCell(self.heap.to_list(chars.into_iter()));
+ let list_of_chars =
+ Addr::HeapCell(self.heap.to_list(chars.into_iter()));
self.unify(a2, list_of_chars);
}
- ref addr if addr.is_ref() => {
+ addr if addr.is_ref() => {
let stub = MachineError::functor_stub(clause_name!("atom_chars"), 2);
- match self.try_from_list(temp_v!(2), stub.clone()) {
- Err(e) => return Err(e),
- Ok(addrs) => match self.try_char_list(addrs) {
- Ok(string) => {
- let chars = clause_name!(string, indices.atom_tbl);
- self.unify(
- addr.clone(),
- Addr::Con(Constant::Atom(chars, None)),
- );
+ match self.try_from_list(temp_v!(2), stub) {
+ Err(e) => {
+ return Err(e);
+ }
+ Ok(addrs) => {
+ match self.try_char_list(addrs) {
+ Ok(string) => {
+ let chars = clause_name!(string, indices.atom_tbl);
+ let atom = self.heap.to_unifiable(
+ HeapCellValue::Atom(chars, None)
+ );
+
+ self.unify(addr, atom);
+ }
+ Err(err) => {
+ let stub = MachineError::functor_stub(
+ clause_name!("atom_chars"),
+ 2,
+ );
+
+ return Err(self.error_form(err, stub));
+ }
}
- Err(err) => return Err(self.error_form(err, stub)),
- },
+ }
}
}
_ => unreachable!(),
let a1 = self[temp_v!(1)].clone();
match self.store(self.deref(a1)) {
- Addr::Con(Constant::Char(c)) => {
- let iter = once(Addr::Con(Constant::CharCode(c as u32)));
+ Addr::Char(c) => {
+ let iter = once(Addr::CharCode(c as u32));
let list_of_codes = Addr::HeapCell(self.heap.to_list(iter));
let a2 = self[temp_v!(2)].clone();
self.unify(a2, list_of_codes);
}
- Addr::Con(Constant::Atom(name, _)) => {
- let a2 = self[temp_v!(2)].clone();
+ Addr::Con(h) if self.heap.atom_at(h) => {
+ if let HeapCellValue::Atom(name, _) = self.heap.clone(h) {
+ let a2 = self[temp_v!(2)];
- match self.store(self.deref(a2)) {
- a2 @ Addr::Con(Constant::String(..)) => {
- if !self.flags.double_quotes.is_codes() {
- self.fail = true;
- } else {
+ match self.store(self.deref(a2)) {
+ a2 @ Addr::PStrLocation(..) => {
+ if !self.flags.double_quotes.is_codes() {
+ self.fail = true;
+ } else {
+ let iter = name
+ .as_str()
+ .chars()
+ .map(|c| Addr::Char(c));
+
+ let list_of_codes = Addr::HeapCell(self.heap.to_list(iter));
+
+ self.unify(a2, list_of_codes);
+ }
+ }
+ a2 => {
let iter = name
.as_str()
.chars()
- .map(|c| Addr::Con(Constant::Char(c)));
+ .map(|c| Addr::CharCode(c as u32));
let list_of_codes = Addr::HeapCell(self.heap.to_list(iter));
self.unify(a2, list_of_codes);
}
}
- a2 => {
- let iter = name
- .as_str()
- .chars()
- .map(|c| Addr::Con(Constant::CharCode(c as u32)));
-
- let list_of_codes = Addr::HeapCell(self.heap.to_list(iter));
-
- self.unify(a2, list_of_codes);
- }
+ } else {
+ unreachable!()
}
}
- Addr::Con(Constant::EmptyList) => {
+ Addr::EmptyList => {
let chars = vec![
- Addr::Con(Constant::CharCode('[' as u32)),
- Addr::Con(Constant::CharCode(']' as u32)),
+ Addr::CharCode('[' as u32),
+ Addr::CharCode(']' as u32),
];
let list_of_codes = Addr::HeapCell(self.heap.to_list(chars.into_iter()));
self.unify(a2, list_of_codes);
}
- ref addr if addr.is_ref() => {
+ addr if addr.is_ref() => {
let stub = MachineError::functor_stub(clause_name!("atom_codes"), 2);
- match self.try_from_list(temp_v!(2), stub.clone()) {
+ match self.try_from_list(temp_v!(2), stub) {
Err(e) => return Err(e),
Ok(addrs) => {
let mut chars = String::new();
for addr in addrs {
match addr {
- Addr::Con(Constant::Integer(n)) => {
- let c = self.int_to_char_code(&n, "atom_codes", 2)?;
- chars.push(std::char::from_u32(c).unwrap());
+ 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!()
+ }
}
- Addr::Con(Constant::CharCode(c)) => {
+ Addr::CharCode(c) => {
chars.push(std::char::from_u32(c).unwrap());
}
_ => {
+ let stub = MachineError::functor_stub(
+ clause_name!("atom_codes"),
+ 2,
+ );
+
let err = MachineError::type_error(
+ self.heap.h(),
ValidType::Integer,
- addr.clone(),
+ addr,
);
+
return Err(self.error_form(err, stub));
}
}
}
let chars = clause_name!(chars, indices.atom_tbl);
- self.unify(addr.clone(), Addr::Con(Constant::Atom(chars, None)));
+ let chars = self.heap.to_unifiable(HeapCellValue::Atom(chars, None));
+
+ self.unify(addr, chars);
}
}
}
};
}
&SystemClauseType::AtomLength => {
- let a1 = self[temp_v!(1)].clone();
+ let a1 = self.store(self.deref(self[temp_v!(1)]));
let atom = match self.store(self.deref(a1)) {
- Addr::Con(Constant::Atom(name, _)) => name,
- Addr::Con(Constant::EmptyList) => clause_name!("[]"),
- Addr::Con(Constant::Char(c)) => clause_name!(c.to_string(), indices.atom_tbl),
- _ => unreachable!(),
+ Addr::Con(h) if self.heap.atom_at(h) => {
+ if let HeapCellValue::Atom(ref name, _) = &self.heap[h] {
+ name.clone()
+ } else {
+ unreachable!()
+ }
+ }
+ Addr::EmptyList => {
+ clause_name!("[]")
+ }
+ Addr::Char(c) => {
+ clause_name!(c.to_string(), indices.atom_tbl)
+ }
+ _ => {
+ unreachable!()
+ }
};
let len = Integer::from(atom.as_str().chars().count());
- let a2 = self[temp_v!(2)].clone();
+ let len = self.heap.to_unifiable(HeapCellValue::Integer(Rc::new(len)));
+
+ let a2 = self[temp_v!(2)];
- self.unify(a2, Addr::Con(Constant::Integer(len)));
+ self.unify(a2, len);
}
&SystemClauseType::CallAttributeGoals => {
let p = self.attr_var_init.project_attrs_loc;
&SystemClauseType::CharsToNumber => {
let stub = MachineError::functor_stub(clause_name!("number_chars"), 2);
- match self.try_from_list(temp_v!(1), stub.clone()) {
- Err(e) => return Err(e),
- Ok(addrs) => match self.try_char_list(addrs) {
- Ok(string) => self.parse_number_from_string(string, indices, stub)?,
- Err(err) => return Err(self.error_form(err, stub)),
- },
+ match self.try_from_list(temp_v!(1), stub) {
+ Err(e) => {
+ return Err(e);
+ }
+ Ok(addrs) => {
+ match self.try_char_list(addrs) {
+ Ok(string) => {
+ let stub = MachineError::functor_stub(clause_name!("number_chars"), 2);
+ self.parse_number_from_string(string, indices, stub)?;
+ }
+ Err(err) => {
+ let stub = MachineError::functor_stub(
+ clause_name!("number_chars"),
+ 2,
+ );
+
+ return Err(self.error_form(err, stub));
+ }
+ }
+ }
}
}
&SystemClauseType::CreatePartialString => {
- let atom = match self.store(self.deref(self[temp_v!(1)].clone())) {
- Addr::Con(Constant::Atom(atom, _)) => {
- atom
+ let atom = match self.store(self.deref(self[temp_v!(1)])) {
+ Addr::Con(h) => {
+ if let HeapCellValue::Atom(ref name, _) = &self.heap[h] {
+ name.clone()
+ } else {
+ unreachable!()
+ }
}
_ => {
unreachable!()
};
let h = self.heap.h();
- let pstr =
- match self.heap.allocate_pstr(atom.as_str()) {
- Some(pstr_addr) => {
- pstr_addr
- }
- None => {
- let stub = MachineError::functor_stub(clause_name!("partial_string"), 3);
- let err = MachineError::representation_error(
- RepFlag::Character,
- );
-
- return Err(self.error_form(err, stub));
- }
- };
+ let pstr = self.heap.allocate_pstr(atom.as_str());
let pstr_tail = self.heap[h + 1].as_addr(h + 1);
-
- self.unify(self[temp_v!(2)].clone(), pstr);
+
+ self.unify(self[temp_v!(2)], pstr);
if !self.fail {
- self.unify(self[temp_v!(3)].clone(), pstr_tail);
+ self.unify(self[temp_v!(3)], pstr_tail);
}
}
&SystemClauseType::IsPartialString => {
}
}
&SystemClauseType::PartialStringTail => {
- let pstr = self.store(self.deref(self[temp_v!(1)].clone()));
+ let pstr = self.store(self.deref(self[temp_v!(1)]));
match pstr {
Addr::PStrLocation(h, _) => {
let tail = self.heap[h + 1].as_addr(h + 1);
- let target = self[temp_v!(2)].clone();
-
+ let target = self[temp_v!(2)];
+
self.unify(tail, target);
}
_ => {
}
}
&SystemClauseType::NumberToChars => {
- let n = self[temp_v!(1)].clone();
- let chs = self[temp_v!(2)].clone();
+ let n = self[temp_v!(1)];
+ let chs = self[temp_v!(2)];
let string = match self.store(self.deref(n)) {
- Addr::Con(Constant::Float(OrderedFloat(n))) => format!("{0:<20?}", n),
- Addr::Con(Constant::Integer(n)) => n.to_string(),
- _ => unreachable!(),
+ 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] {
+ n.to_string()
+ } else {
+ unreachable!()
+ }
+ }
+ _ => {
+ unreachable!()
+ }
};
- let chars = string.trim().chars().map(|c| Addr::Con(Constant::Char(c)));
+ let chars = string.trim().chars().map(|c| Addr::Char(c));
let char_list = Addr::HeapCell(self.heap.to_list(chars));
self.unify(char_list, chs);
}
&SystemClauseType::NumberToCodes => {
- let n = self[temp_v!(1)].clone();
- let chs = self[temp_v!(2)].clone();
+ let n = self[temp_v!(1)];
+ let chs = self[temp_v!(2)];
let string = match self.store(self.deref(n)) {
- Addr::Con(Constant::Float(OrderedFloat(n))) => format!("{0:<20?}", n),
- Addr::Con(Constant::Integer(n)) => n.to_string(),
- _ => unreachable!(),
+ 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] {
+ n.to_string()
+ } else {
+ unreachable!()
+ }
+ }
+ _ => {
+ unreachable!()
+ }
};
let codes = string
.trim()
.chars()
- .map(|c| Addr::Con(Constant::CharCode(c as u32)));
+ .map(|c| Addr::CharCode(c as u32));
+
let codes_list = Addr::HeapCell(self.heap.to_list(codes));
self.unify(codes_list, chs);
&SystemClauseType::CodesToNumber => {
let stub = MachineError::functor_stub(clause_name!("number_codes"), 2);
- match self.try_from_list(temp_v!(1), stub.clone()) {
- Err(e) => return Err(e),
- Ok(addrs) => match self.try_char_list(addrs) {
- Ok(chars) => {
- self.parse_number_from_string(chars, indices, stub)?
+ match self.try_from_list(temp_v!(1), stub) {
+ Err(e) => {
+ return Err(e);
+ }
+ Ok(addrs) => {
+ match self.try_char_list(addrs) {
+ Ok(chars) => {
+ let stub = MachineError::functor_stub(clause_name!("number_codes"), 2);
+ self.parse_number_from_string(chars, indices, stub)?;
+ }
+ Err(err) => {
+ let stub = MachineError::functor_stub(
+ clause_name!("number_codes"),
+ 2,
+ );
+
+ return Err(self.error_form(err, stub));
+ }
}
- Err(err) => return Err(self.error_form(err, stub)),
- },
+ }
}
}
&SystemClauseType::ModuleAssertDynamicPredicateToFront => {
}
&SystemClauseType::LiftedHeapLength => {
let a1 = self[temp_v!(1)].clone();
- let lh_len = Addr::Con(Constant::Usize(self.lifted_heap.h()));
+ let lh_len = Addr::Usize(self.lifted_heap.h());
self.unify(a1, lh_len);
}
&SystemClauseType::CharCode => {
- let a1 = self[temp_v!(1)].clone();
+ let a1 = self[temp_v!(1)];
match self.store(self.deref(a1)) {
- Addr::Con(Constant::Atom(name, _)) => {
- let c = name.as_str().chars().next().unwrap();
- let a2 = self[temp_v!(2)].clone();
- let c = Integer::from(c as u32);
+ Addr::Con(h) if self.heap.atom_at(h) => {
+ let c =
+ if let HeapCellValue::Atom(name, _) = &self.heap[h] {
+ if name.is_char() {
+ name.as_str().chars().next().unwrap()
+ } else {
+ self.fail = true;
+ return Ok(());
+ }
+ } else {
+ unreachable!()
+ };
- self.unify(Addr::Con(Constant::Integer(c)), a2);
+ let a2 = self[temp_v!(2)];
+ self.unify(Addr::CharCode(c as u32), a2);
}
- Addr::Con(Constant::Char(c)) => {
- let a2 = self[temp_v!(2)].clone();
- let c = Integer::from(c as u32);
-
- self.unify(Addr::Con(Constant::Integer(c)), a2);
+ Addr::Char(c) => {
+ let a2 = self[temp_v!(2)];
+ self.unify(Addr::CharCode(c as u32), a2);
}
addr if addr.is_ref() => {
- let a2 = self[temp_v!(2)].clone();
+ let a2 = self[temp_v!(2)];
match self.store(self.deref(a2)) {
- Addr::Con(Constant::CharCode(code)) => {
+ Addr::CharCode(code) => {
if let Some(c) = std::char::from_u32(code) {
- self.unify(Addr::Con(Constant::Char(c)), addr);
+ self.unify(Addr::Char(c), addr);
} else {
self.fail = true;
}
}
- Addr::Con(Constant::Integer(n)) => {
- let c = 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::Con(Constant::Char(c)), addr);
+ self.unify(Addr::Char(c), addr);
} else {
self.fail = true;
}
let addr = self.store(self.deref(self[temp_v!(1)].clone()));
match addr {
- Addr::Con(Constant::Usize(old_b)) | Addr::Con(Constant::CutPoint(old_b)) => {
+ Addr::Usize(old_b) | Addr::CutPoint(old_b) => {
let prev_b = self.stack.index_or_frame(self.b).prelude.b;
let prev_b = self.stack.index_or_frame(prev_b).prelude.b;
self.copy_term(AttrVarPolicy::StripAttributes);
}
&SystemClauseType::FetchGlobalVar => {
- let key = self[temp_v!(1)].clone();
+ let key = self[temp_v!(1)];
let key = match self.store(self.deref(key)) {
- Addr::Con(Constant::Atom(atom, _)) => atom,
- _ => unreachable!(),
+ Addr::Con(h) if self.heap.atom_at(h) => {
+ if let HeapCellValue::Atom(ref atom, _) = &self.heap[h] {
+ atom.clone()
+ } else {
+ unreachable!()
+ }
+ }
+ _ => {
+ unreachable!()
+ }
};
- let addr = self[temp_v!(2)].clone();
+ let addr = self[temp_v!(2)];
match indices.global_variables.get_mut(&key) {
Some((ref mut ball, None)) => {
let key = self[temp_v!(1)].clone();
let key = match self.store(self.deref(key)) {
- Addr::Con(Constant::Atom(atom, _)) => atom,
- _ => unreachable!(),
+ Addr::Con(h) if self.heap.atom_at(h) => {
+ if let HeapCellValue::Atom(ref atom, _) = &self.heap[h] {
+ atom.clone()
+ } else {
+ unreachable!()
+ }
+ }
+ _ => {
+ unreachable!()
+ }
};
- let addr = self[temp_v!(2)].clone();
+ let addr = self[temp_v!(2)];
match indices.global_variables.get_mut(&key) {
Some((ref mut ball, ref mut offset @ None)) => {
Some((_, Some(h))) => {
let offset = self[temp_v!(3)].clone();
- self.unify(offset, Addr::Con(Constant::Usize(*h)));
+ self.unify(offset, Addr::Usize(*h));
if !self.fail {
self.unify(addr, Addr::HeapCell(*h));
let a1 = self[temp_v!(1)].clone();
match result {
- Some(Ok(b)) => self.unify(Addr::Con(Constant::Char(b as char)), a1),
+ Some(Ok(b)) => {
+ self.unify(Addr::Char(b as char), a1);
+ }
Some(Err(_)) => {
- let end_of_file = clause_name!("end_of_file");
- self.unify(a1, Addr::Con(Constant::Atom(end_of_file, None)));
+ let end_of_file = self.heap.to_unifiable(HeapCellValue::Atom(
+ clause_name!("end_of_file"),
+ None,
+ ));
+
+ self.unify(a1, end_of_file);
}
None => {
let stub = MachineError::functor_stub(clause_name!("get_char"), 1);
}
}
&SystemClauseType::GetModuleClause => {
- let module = self[temp_v!(3)].clone();
- let head = self[temp_v!(1)].clone();
+ let module = self[temp_v!(3)];
+ let head = self[temp_v!(1)];
let module = match self.store(self.deref(module)) {
- Addr::Con(Constant::Atom(module, _)) => module,
+ Addr::Con(h) if self.heap.atom_at(h) => {
+ if let HeapCellValue::Atom(module, _) = &self.heap[h] {
+ module.clone()
+ } else {
+ unreachable!()
+ }
+ }
_ => {
self.fail = true;
return Ok(());
};
let subsection = match self.store(self.deref(head)) {
- Addr::Str(s) => match self.heap[s].clone() {
- HeapCellValue::NamedStr(arity, name, ..) => {
- indices.get_clause_subsection(module, name, arity)
+ Addr::Str(s) => match &self.heap[s] {
+ &HeapCellValue::NamedStr(arity, ref name, ..) => {
+ indices.get_clause_subsection(module, name.clone(), arity)
+ }
+ _ => {
+ unreachable!()
}
- _ => unreachable!(),
},
- Addr::Con(Constant::Atom(name, _)) => {
- indices.get_clause_subsection(module, name, 0)
+ Addr::Con(h) => {
+ if let HeapCellValue::Atom(name, _) = &self.heap[h] {
+ indices.get_clause_subsection(module, name.clone(), 0)
+ } else {
+ unreachable!()
+ }
+ }
+
+ _ => {
+ unreachable!()
}
- _ => unreachable!(),
};
match subsection {
Some(dynamic_predicate_info) => {
self.execute_at_index(
2,
- dir_entry!(dynamic_predicate_info.clauses_subsection_p)
+ dir_entry!(dynamic_predicate_info.clauses_subsection_p),
);
+
return Ok(());
}
- None => self.fail = true,
+ None => {
+ self.fail = true;
+ }
}
}
&SystemClauseType::ModuleHeadIsDynamic => {
- let module = self[temp_v!(2)].clone();
- let head = self[temp_v!(1)].clone();
+ let module = self[temp_v!(2)];
+ let head = self[temp_v!(1)];
let module = match self.store(self.deref(module)) {
- Addr::Con(Constant::Atom(module, _)) => module,
+ Addr::Con(h) if self.heap.atom_at(h) =>
+ if let HeapCellValue::Atom(module, _) = &self.heap[h] {
+ module.clone()
+ } else {
+ unreachable!()
+ }
_ => {
self.fail = true;
return Ok(());
};
self.fail = !match self.store(self.deref(head)) {
- Addr::Str(s) => match self.heap[s].clone() {
- HeapCellValue::NamedStr(arity, name, ..) => {
- indices.get_clause_subsection(module, name, arity).is_some()
+ Addr::Str(s) => match &self.heap[s] {
+ &HeapCellValue::NamedStr(arity, ref name, ..) => {
+ indices.get_clause_subsection(module, name.clone(), arity)
+ .is_some()
}
_ => unreachable!(),
},
- Addr::Con(Constant::Atom(name, _)) => {
- indices.get_clause_subsection(module, name, 0).is_some()
+ Addr::Con(h) => {
+ if let HeapCellValue::Atom(name, _) = &self.heap[h] {
+ indices.get_clause_subsection(module, name.clone(), 0)
+ .is_some()
+ } else {
+ unreachable!()
+ }
}
_ => unreachable!(),
};
let head = self[temp_v!(1)].clone();
self.fail = !match self.store(self.deref(head)) {
- Addr::Str(s) => match self.heap[s].clone() {
- HeapCellValue::NamedStr(arity, name, ..) => indices
- .get_clause_subsection(name.owning_module(), name, arity)
+ Addr::Str(s) => match &self.heap[s] {
+ &HeapCellValue::NamedStr(arity, ref name, ..) => indices
+ .get_clause_subsection(name.owning_module(), name.clone(), arity)
.is_some(),
_ => unreachable!(),
},
- Addr::Con(Constant::Atom(name, _)) => indices
- .get_clause_subsection(name.owning_module(), name, 0)
- .is_some(),
- _ => unreachable!(),
+ Addr::Con(h) if self.heap.atom_at(h) => {
+ if let HeapCellValue::Atom(name, _) = &self.heap[h] {
+ indices.get_clause_subsection(name.owning_module(), name.clone(), 0)
+ .is_some()
+ } else {
+ unreachable!()
+ }
+ }
+ _ => {
+ unreachable!()
+ }
};
}
&SystemClauseType::CopyToLiftedHeap => {
- match self.store(self.deref(self[temp_v!(1)].clone())) {
- Addr::Con(Constant::Usize(lh_offset)) => {
- let copy_target = self[temp_v!(2)].clone();
+ match self.store(self.deref(self[temp_v!(1)])) {
+ Addr::Usize(lh_offset) => {
+ let copy_target = self[temp_v!(2)];
let old_threshold = self.copy_findall_solution(lh_offset, copy_target);
let new_threshold = self.lifted_heap.h() - lh_offset;
}
}
}
- _ => self.fail = true,
+ _ => {
+ self.fail = true;
+ }
}
}
&SystemClauseType::DeleteAttribute => {
- let ls0 = self.store(self.deref(self[temp_v!(1)].clone()));
+ let ls0 = self.store(self.deref(self[temp_v!(1)]));
if let Addr::Lis(l1) = ls0 {
if let Addr::Lis(l2) = self.store(self.deref(Addr::HeapCell(l1 + 1))) {
let old_addr = self.heap[l1 + 1].as_addr(l1 + 1);
-
let tail = self.store(self.deref(Addr::HeapCell(l2 + 1)));
+
let tail = if tail.is_ref() {
Addr::HeapCell(l1 + 1)
} else {
}
}
&SystemClauseType::DeleteHeadAttribute => {
- let addr = self.store(self.deref(self[temp_v!(1)].clone()));
+ let addr = self.store(self.deref(self[temp_v!(1)]));
match addr {
Addr::AttrVar(h) => {
- let addr = self.heap[h + 1].as_addr(h + 1).clone();
+ let addr = self.heap[h + 1].as_addr(h + 1);
let addr = self.store(self.deref(addr));
match addr {
}
}
&SystemClauseType::DynamicModuleResolution(narity) => {
- let module_name = self.store(self.deref(self[temp_v!(1 + narity)].clone()));
-
- if let Addr::Con(Constant::Atom(module_name, _)) = module_name {
- match self.store(self.deref(self[temp_v!(2 + narity)].clone())) {
- Addr::Str(a) => {
- if let HeapCellValue::NamedStr(arity, name, _) = self.heap[a].clone() {
- for i in (arity + 1 .. arity + narity + 1).rev() {
- self.registers[i] = self.registers[i - arity].clone();
- }
+ let module_name = self.store(self.deref(self[temp_v!(1 + narity)]));
- for i in 1 .. arity + 1 {
- self.registers[i] = self.heap[a + i].as_addr(a + i);
- }
+ let module_name = match module_name {
+ Addr::Con(h) if self.heap.atom_at(h) => {
+ if let HeapCellValue::Atom(ref module_name, _) = self.heap[h] {
+ module_name.clone()
+ } else {
+ unreachable!()
+ }
+ }
+ _ => {
+ unreachable!()
+ }
+ };
- return self.module_lookup(
- indices,
- (name, arity + narity),
- module_name,
- true,
- );
+ match self.store(self.deref(self[temp_v!(2 + narity)])) {
+ Addr::Str(a) => {
+ if let HeapCellValue::NamedStr(arity, name, _) = self.heap.clone(a) {
+ for i in (arity + 1 .. arity + narity + 1).rev() {
+ self.registers[i] = self.registers[i - arity];
}
+
+ for i in 1 .. arity + 1 {
+ self.registers[i] = self.heap[a + i].as_addr(a + i);
+ }
+
+ return self.module_lookup(
+ indices,
+ (name, arity + narity),
+ module_name,
+ true,
+ );
+ } else {
+ unreachable!()
}
- Addr::Con(Constant::Atom(name, _)) => {
- return self.module_lookup(indices, (name, narity), module_name, true)
+ }
+ Addr::Con(h) if self.heap.atom_at(h) => {
+ if let HeapCellValue::Atom(name, _) = self.heap.clone(h) {
+ return self.module_lookup(
+ indices,
+ (name.clone(), narity),
+ module_name,
+ true,
+ );
+ } else {
+ unreachable!()
}
- addr => {
- let stub = MachineError::functor_stub(clause_name!("(:)"), 2);
+ }
+ addr => {
+ let stub = MachineError::functor_stub(clause_name!("(:)"), 2);
- let type_error = MachineError::type_error(ValidType::Callable, addr);
- let type_error = self.error_form(type_error, stub);
+ let type_error = MachineError::type_error(
+ self.heap.h(),
+ ValidType::Callable,
+ addr,
+ );
- return Err(type_error);
- }
+ let type_error = self.error_form(type_error, stub);
+ return Err(type_error);
}
- };
+ }
}
&SystemClauseType::EnqueueAttributeGoal => {
- let addr = self[temp_v!(1)].clone();
+ let addr = self[temp_v!(1)];
self.attr_var_init.attribute_goals.push(addr);
}
&SystemClauseType::EnqueueAttributedVar => {
- let addr = self[temp_v!(1)].clone();
+ let addr = self[temp_v!(1)];
match self.store(self.deref(addr)) {
- Addr::AttrVar(h) => self.attr_var_init.attr_var_queue.push(h),
- _ => {}
+ Addr::AttrVar(h) => {
+ self.attr_var_init.attr_var_queue.push(h);
+ }
+ _ => {
+ }
}
}
&SystemClauseType::ExpandGoal => {
return Ok(());
}
&SystemClauseType::GetNextDBRef => {
- let a1 = self[temp_v!(1)].clone();
+ let a1 = self[temp_v!(1)];
match self.store(self.deref(a1)) {
addr @ Addr::HeapCell(_)
- | addr @ Addr::StackCell(..)
- | addr @ Addr::AttrVar(_) => {
+ | addr @ Addr::StackCell(..)
+ | addr @ Addr::AttrVar(_) => {
let mut iter = indices.code_dir.iter();
while let Some(((name, arity), _)) = iter.next() {
*arity,
composite_op!(&indices.op_dir),
);
+
let db_ref = DBRef::NamedPred(name.clone(), *arity, spec);
let r = addr.as_var().unwrap();
- self.bind(r, Addr::DBRef(db_ref));
+ let addr = self.heap.to_unifiable(
+ HeapCellValue::DBRef(db_ref)
+ );
+
+ self.bind(r, addr);
+
return return_from_clause!(self.last_call, self);
}
self.fail = true;
}
- Addr::DBRef(DBRef::Op(..)) => self.fail = true,
- Addr::DBRef(ref db_ref) => self.get_next_db_ref(&indices, db_ref),
+ Addr::Con(h) => {
+ match self.heap.clone(h) {
+ HeapCellValue::DBRef(DBRef::Op(..)) => {
+ self.fail = true;
+ }
+ HeapCellValue::DBRef(ref db_ref) => {
+ self.get_next_db_ref(indices, db_ref);
+ }
+ _ => {
+ self.fail = true;
+ }
+ }
+ }
_ => {
self.fail = true;
}
- };
+ }
}
&SystemClauseType::GetNextOpDBRef => {
- let a1 = self[temp_v!(1)].clone();
+ let a1 = self[temp_v!(1)];
match self.store(self.deref(a1)) {
addr @ Addr::HeapCell(_)
- | addr @ Addr::StackCell(..)
- | addr @ Addr::AttrVar(_) => {
+ | addr @ Addr::StackCell(..)
+ | addr @ Addr::AttrVar(_) => {
let mut unossified_op_dir = OssifiedOpDir::new();
unossified_op_dir.extend(indices.op_dir.iter().filter_map(
ossified_op_dir.clone(),
SharedOpDesc::new(*priority, *spec),
);
+
let r = addr.as_var().unwrap();
+ let addr = self.heap.to_unifiable(
+ HeapCellValue::DBRef(db_ref)
+ );
- self.bind(r, Addr::DBRef(db_ref));
+ self.bind(r, addr);
}
None => {
self.fail = true;
}
}
}
- Addr::DBRef(DBRef::NamedPred(..)) => self.fail = true,
- Addr::DBRef(ref db_ref) => self.get_next_db_ref(&indices, db_ref),
+ Addr::Con(h) => {
+ match self.heap.clone(h) {
+ HeapCellValue::DBRef(DBRef::NamedPred(..)) => {
+ self.fail = true;
+ }
+ HeapCellValue::DBRef(ref db_ref) => {
+ self.get_next_db_ref(indices, db_ref);
+ }
+ _ => {
+ self.fail = true;
+ }
+ }
+ }
_ => {
self.fail = true;
}
}
}
&SystemClauseType::LookupDBRef => {
- let a1 = self[temp_v!(1)].clone();
+ let a1 = self[temp_v!(1)];
match self.store(self.deref(a1)) {
- Addr::DBRef(db_ref) => match db_ref {
- DBRef::NamedPred(name, arity, spec) => {
- let a2 = self[temp_v!(2)].clone();
- let a3 = self[temp_v!(3)].clone();
-
- let arity = Integer::from(arity);
+ Addr::Con(h) => {
+ match self.heap.clone(h) {
+ HeapCellValue::DBRef(DBRef::NamedPred(name, arity, spec)) => {
+ let a2 = self[temp_v!(2)];
+ let a3 = self[temp_v!(3)];
+
+ let atom = self.heap.to_unifiable(
+ HeapCellValue::Atom(name, spec)
+ );
- self.unify(a2, Addr::Con(Constant::Atom(name, spec)));
+ self.unify(a2, atom);
- if !self.fail {
- self.unify(a3, Addr::Con(Constant::Integer(arity)));
+ if !self.fail {
+ self.unify(a3, Addr::Usize(arity));
+ }
+ }
+ _ => {
+ self.fail = true;
}
}
- _ => self.fail = true,
- },
- _ => self.fail = true,
+ }
+ _ => {
+ self.fail = true;
+ }
}
}
&SystemClauseType::LookupOpDBRef => {
- let a1 = self[temp_v!(1)].clone();
+ let a1 = self[temp_v!(1)];
match self.store(self.deref(a1)) {
- Addr::DBRef(db_ref) => match db_ref {
- DBRef::Op(priority, spec, name, _, shared_op_desc) => {
- let prec = self[temp_v!(2)].clone();
- let specifier = self[temp_v!(3)].clone();
- let op = self[temp_v!(4)].clone();
-
- let spec = match spec {
- FX => "fx",
- FY => "fy",
- XF => "xf",
- YF => "yf",
- XFX => "xfx",
- XFY => "xfy",
- YFX => "yfx",
- _ => {
- self.fail = true;
- return Ok(());
- }
- };
+ Addr::Con(h) => {
+ match self.heap.clone(h) {
+ HeapCellValue::DBRef(DBRef::Op(
+ priority,
+ spec,
+ name,
+ _,
+ shared_op_desc,
+ )) => {
+ let prec = self[temp_v!(2)];
+ let specifier = self[temp_v!(3)];
+ let op = self[temp_v!(4)];
+
+ let spec = match spec {
+ FX => "fx",
+ FY => "fy",
+ XF => "xf",
+ YF => "yf",
+ XFX => "xfx",
+ XFY => "xfy",
+ YFX => "yfx",
+ _ => {
+ self.fail = true;
+ return Ok(());
+ }
+ };
+
+ let a3 = self.heap.to_unifiable(
+ HeapCellValue::Atom(clause_name!(spec), None)
+ );
- let a2 = Integer::from(priority);
- let a3 = Addr::Con(Constant::Atom(clause_name!(spec), None));
- let a4 = Addr::Con(Constant::Atom(name, Some(shared_op_desc)));
+ let a4 = self.heap.to_unifiable(
+ HeapCellValue::Atom(name, Some(shared_op_desc))
+ );
- self.unify(Addr::Con(Constant::Integer(a2)), prec);
+ self.unify(Addr::Usize(priority), prec);
- if !self.fail {
- self.unify(a3, specifier);
- }
+ if !self.fail {
+ self.unify(a3, specifier);
+ }
- if !self.fail {
- self.unify(a4, op);
+ if !self.fail {
+ self.unify(a4, op);
+ }
+ }
+ _ => {
+ self.fail = true;
}
}
- _ => self.fail = true,
- },
- _ => self.fail = true,
+ }
+ _ => {
+ self.fail = true;
+ }
}
}
&SystemClauseType::Maybe => {
let result = {
let mut rand = RANDOM_STATE.borrow_mut();
-
rand.bits(1) == 0
};
self.fail = result;
}
&SystemClauseType::OpDeclaration => {
- let priority = self[temp_v!(1)].clone();
- let specifier = self[temp_v!(2)].clone();
- let op = self[temp_v!(3)].clone();
+ let priority = self[temp_v!(1)];
+ let specifier = self[temp_v!(2)];
+ let op = self[temp_v!(3)];
let priority = match self.store(self.deref(priority)) {
- Addr::Con(Constant::Integer(n)) => n.to_usize().unwrap(),
- _ => unreachable!(),
+ Addr::Con(h) if self.heap.integer_at(h) =>
+ if let HeapCellValue::Integer(ref n) = &self.heap[h] {
+ n.to_usize().unwrap()
+ } else {
+ unreachable!()
+ },
+ _ =>
+ unreachable!(),
};
let specifier = match self.store(self.deref(specifier)) {
- Addr::Con(Constant::Atom(name, _)) => name,
- _ => unreachable!(),
+ Addr::Con(h) if self.heap.atom_at(h) =>
+ if let HeapCellValue::Atom(ref specifier, _) = &self.heap[h] {
+ specifier.clone()
+ } else {
+ unreachable!()
+ },
+ _ =>
+ unreachable!(),
};
let op = match self.store(self.deref(op)) {
- Addr::Con(Constant::Atom(name, _)) => name,
- Addr::Con(Constant::Char(c)) => clause_name!(c.to_string(), indices.atom_tbl),
- _ => unreachable!(),
+ Addr::Char(c) =>
+ clause_name!(c.to_string(), indices.atom_tbl),
+ Addr::Con(h) if self.heap.atom_at(h) =>
+ if let HeapCellValue::Atom(ref name, _) = &self.heap[h] {
+ name.clone()
+ } else {
+ unreachable!()
+ },
+ _ =>
+ unreachable!(),
};
let module = op.owning_module();
});
match result {
- Ok(()) => {}
+ Ok(()) => {
+ }
Err(e) => {
// 8.14.3.3 l)
let e = MachineError::session_error(self.heap.h(), e);
self.truncate_if_no_lifted_heap_diff(|h| Addr::HeapCell(h))
}
&SystemClauseType::TruncateIfNoLiftedHeapGrowth => {
- self.truncate_if_no_lifted_heap_diff(|_| Addr::Con(Constant::EmptyList))
+ self.truncate_if_no_lifted_heap_diff(|_| Addr::EmptyList)
}
&SystemClauseType::ClearAttributeGoals => {
self.attr_var_init.attribute_goals.clear();
self.fetch_attribute_goals(attr_goals);
}
&SystemClauseType::GetAttributedVariableList => {
- let attr_var = self.store(self.deref(self[temp_v!(1)].clone()));
- let attr_var_list = match attr_var {
- Addr::AttrVar(h) => h + 1,
- attr_var @ Addr::HeapCell(_) | attr_var @ Addr::StackCell(..) => {
- // create an AttrVar in the heap.
- let h = self.heap.h();
+ let attr_var = self.store(self.deref(self[temp_v!(1)]));
+ let attr_var_list =
+ match attr_var {
+ Addr::AttrVar(h) => {
+ h + 1
+ }
+ attr_var @ Addr::HeapCell(_)
+ | attr_var @ Addr::StackCell(..) => {
+ // create an AttrVar in the heap.
+ let h = self.heap.h();
- self.heap.push(HeapCellValue::Addr(Addr::AttrVar(h)));
- self.heap.push(HeapCellValue::Addr(Addr::HeapCell(h + 1)));
+ self.heap.push(HeapCellValue::Addr(Addr::AttrVar(h)));
+ self.heap.push(HeapCellValue::Addr(Addr::HeapCell(h + 1)));
- self.bind(Ref::AttrVar(h), attr_var);
- h + 1
- }
- _ => {
- self.fail = true;
- return Ok(());
- }
- };
+ self.bind(Ref::AttrVar(h), attr_var);
+ h + 1
+ }
+ _ => {
+ self.fail = true;
+ return Ok(());
+ }
+ };
- let list_addr = self[temp_v!(2)].clone();
+ let list_addr = self[temp_v!(2)];
self.unify(Addr::HeapCell(attr_var_list), list_addr);
}
&SystemClauseType::GetAttrVarQueueDelimiter => {
- let addr = self[temp_v!(1)].clone();
- let value = Addr::Con(Constant::Usize(self.attr_var_init.attr_var_queue.len()));
+ let addr = self[temp_v!(1)];
+ let value = Addr::Usize(self.attr_var_init.attr_var_queue.len());
self.unify(addr, value);
}
&SystemClauseType::GetAttrVarQueueBeyond => {
- let addr = self[temp_v!(1)].clone();
+ let addr = self[temp_v!(1)];
match self.store(self.deref(addr)) {
- Addr::Con(Constant::Usize(b)) => {
+ 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)].clone();
+ let list_addr = self[temp_v!(2)];
self.unify(var_list_addr, list_addr);
}
- Addr::Con(Constant::Integer(n)) => {
- if let Some(b) = n.to_usize() {
- let iter = self.gather_attr_vars_created_since(b);
+ Addr::Con(h) if self.heap.integer_at(h) => {
+ if let HeapCellValue::Integer(n) = self.heap.clone(h) {
+ if let Some(b) = n.to_usize() {
+ let iter = self.gather_attr_vars_created_since(b);
- let var_list_addr = Addr::HeapCell(self.heap.to_list(iter));
- let list_addr = self[temp_v!(2)].clone();
+ let var_list_addr = Addr::HeapCell(self.heap.to_list(iter));
+ let list_addr = self[temp_v!(2)].clone();
- self.unify(var_list_addr, list_addr);
+ self.unify(var_list_addr, list_addr);
+ } else {
+ self.fail = true;
+ }
} else {
- self.fail = true;
+ unreachable!()
}
}
- _ => self.fail = true,
+ _ => {
+ self.fail = true;
+ }
}
}
&SystemClauseType::GetContinuationChunk => {
- let e = self.store(self.deref(self[temp_v!(1)].clone()));
+ let e = self.store(self.deref(self[temp_v!(1)]));
- let e = if let Addr::Con(Constant::Usize(e)) = e {
+ let e = if let Addr::Usize(e) = e {
e
} else {
self.fail = true;
return Ok(());
};
- let p_functor = self.store(self.deref(self[temp_v!(2)].clone()));
+ let p_functor = self.store(self.deref(self[temp_v!(2)]));
let p = self.heap.to_local_code_ptr(&p_functor).unwrap();
- let num_cells = match code_repo.lookup_instr(self.last_call, &CodePtr::Local(p)) {
- Some(line) => {
- let perm_vars = match line.as_ref() {
- Line::Control(ref ctrl_instr) => ctrl_instr.perm_vars(),
- _ => None
- };
+ let num_cells =
+ match code_repo.lookup_instr(self.last_call, &CodePtr::Local(p)) {
+ Some(line) => {
+ let perm_vars = match line.as_ref() {
+ Line::Control(ref ctrl_instr) => ctrl_instr.perm_vars(),
+ _ => None
+ };
- perm_vars.unwrap()
- }
- _ => unreachable!()
- };
+ perm_vars.unwrap()
+ }
+ _ => unreachable!()
+ };
let mut addrs = vec![];
for index in 1 .. num_cells + 1 {
- addrs.push(self.stack.index_and_frame(e)[index].clone());
+ addrs.push(self.stack.index_and_frame(e)[index]);
}
let chunk = Addr::HeapCell(self.heap.h());
self.heap.push(HeapCellValue::Addr(p_functor));
self.heap.extend(addrs.into_iter().map(HeapCellValue::Addr));
- self.unify(self[temp_v!(3)].clone(), chunk);
+ self.unify(self[temp_v!(3)], chunk);
}
&SystemClauseType::GetLiftedHeapFromOffsetDiff => {
- let lh_offset = self[temp_v!(1)].clone();
+ let lh_offset = self[temp_v!(1)];
match self.store(self.deref(lh_offset)) {
- Addr::Con(Constant::Usize(lh_offset)) => {
+ Addr::Usize(lh_offset) => {
if lh_offset >= self.lifted_heap.h() {
- let solutions = self[temp_v!(2)].clone();
- let diff = self[temp_v!(3)].clone();
+ let solutions = self[temp_v!(2)];
+ let diff = self[temp_v!(3)];
- self.unify(solutions, Addr::Con(Constant::EmptyList));
- self.unify(diff, Addr::Con(Constant::EmptyList));
+ self.unify(solutions, Addr::EmptyList);
+ self.unify(diff, Addr::EmptyList);
} else {
let h = self.heap.h();
let mut last_index = h;
match value {
HeapCellValue::Addr(ref addr) => {
- self.heap.push(HeapCellValue::Addr(addr.clone() + h));
- }
- HeapCellValue::PartialString(ref pstr) => {
- let new_pstr = pstr.clone();
- self.heap.push(HeapCellValue::PartialString(new_pstr));
+ self.heap.push(HeapCellValue::Addr(*addr + h));
}
value => {
- self.heap.push(value.clone());
+ self.heap.push(value.context_free_clone());
}
}
}
if last_index < self.heap.h() {
let addr_opt =
if let HeapCellValue::Addr(ref addr) = &self.heap[last_index] {
- Some(addr.clone())
+ Some(*addr)
} else {
None
};
addr_opt.map(|addr| {
- let diff = self[temp_v!(3)].clone();
+ let diff = self[temp_v!(3)];
self.unify(diff, addr);
});
}
self.lifted_heap.truncate(lh_offset);
- let solutions = self[temp_v!(2)].clone();
+ let solutions = self[temp_v!(2)];
self.unify(Addr::HeapCell(h), solutions);
}
}
- _ => self.fail = true,
+ _ => {
+ self.fail = true;
+ }
}
}
&SystemClauseType::GetLiftedHeapFromOffset => {
- let lh_offset = self[temp_v!(1)].clone();
+ let lh_offset = self[temp_v!(1)];
match self.store(self.deref(lh_offset)) {
- Addr::Con(Constant::Usize(lh_offset)) => {
+ Addr::Usize(lh_offset) => {
if lh_offset >= self.lifted_heap.h() {
- let solutions = self[temp_v!(2)].clone();
- self.unify(solutions, Addr::Con(Constant::EmptyList));
+ let solutions = self[temp_v!(2)];
+ self.unify(solutions, Addr::EmptyList);
} else {
let h = self.heap.h();
for addr in self.lifted_heap.iter_from(lh_offset) {
match addr {
HeapCellValue::Addr(ref addr) => {
- self.heap.push(HeapCellValue::Addr(addr.clone() + h))
- }
- HeapCellValue::PartialString(ref pstr) => {
- let new_pstr = pstr.clone();
- self.heap.push(HeapCellValue::PartialString(new_pstr));
+ self.heap.push(HeapCellValue::Addr(*addr + h));
}
value => {
- self.heap.push(value.clone());
+ self.heap.push(value.context_free_clone());
}
}
}
self.lifted_heap.truncate(lh_offset);
- let solutions = self[temp_v!(2)].clone();
+ let solutions = self[temp_v!(2)];
self.unify(Addr::HeapCell(h), solutions);
}
}
- _ => self.fail = true,
+ _ => {
+ self.fail = true;
+ }
}
}
&SystemClauseType::GetDoubleQuotes => {
- let a1 = self[temp_v!(1)].clone();
+ let a1 = self[temp_v!(1)];
match self.flags.double_quotes {
- DoubleQuotes::Chars => self.unify(a1, Addr::Con(atom!("chars"))),
- DoubleQuotes::Atom => self.unify(a1, Addr::Con(atom!("atom"))),
- DoubleQuotes::Codes => self.unify(a1, Addr::Con(atom!("codes"))),
+ DoubleQuotes::Chars => {
+ let atom = self.heap.to_unifiable(
+ HeapCellValue::Atom(clause_name!("chars"), None)
+ );
+
+ self.unify(a1, atom);
+ }
+ DoubleQuotes::Atom => {
+ let atom = self.heap.to_unifiable(
+ HeapCellValue::Atom(clause_name!("atom"), None)
+ );
+
+ self.unify(a1, atom);
+ }
+ DoubleQuotes::Codes => {
+ let atom = self.heap.to_unifiable(
+ HeapCellValue::Atom(clause_name!("codes"), None)
+ );
+
+ self.unify(a1, atom);
+ }
}
}
&SystemClauseType::GetSCCCleaner => {
- let dest = self[temp_v!(1)].clone();
+ let dest = self[temp_v!(1)];
match cut_policy.downcast_mut::<SCCCutPolicy>().ok() {
Some(sgc_policy) => {
self.block = prev_b;
if let Some(r) = dest.as_var() {
- self.bind(r, addr.clone());
+ self.bind(r, addr);
return return_from_clause!(self.last_call, self);
}
} else {
self.fail = true;
}
- &SystemClauseType::Halt => std::process::exit(0),
+ &SystemClauseType::Halt => {
+ std::process::exit(0);
+ }
&SystemClauseType::InstallSCCCleaner => {
- let addr = self[temp_v!(1)].clone();
+ let addr = self[temp_v!(1)];
let b = self.b;
let prev_block = self.block;
}
&SystemClauseType::InstallInferenceCounter => {
// A1 = B, A2 = L
- let a1 = self.store(self.deref(self[temp_v!(1)].clone()));
- let a2 = self.store(self.deref(self[temp_v!(2)].clone()));
+ let a1 = self.store(self.deref(self[temp_v!(1)]));
+ let a2 = self.store(self.deref(self[temp_v!(2)]));
if call_policy.downcast_ref::<CWILCallPolicy>().is_err() {
CWILCallPolicy::new_in_place(call_policy);
}
- match (a1, a2.clone()) {
- (Addr::Con(Constant::Usize(bp)), Addr::Con(Constant::Integer(n)))
- | (Addr::Con(Constant::CutPoint(bp)), Addr::Con(Constant::Integer(n))) => {
- match call_policy.downcast_mut::<CWILCallPolicy>().ok() {
- Some(call_policy) => {
- let count = call_policy.add_limit(n, bp);
- let count = Addr::Con(Constant::Integer(count.clone()));
+ 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 a3 = self[temp_v!(3)].clone();
+ let a3 = self[temp_v!(3)];
- self.unify(a3, count);
+ self.unify(a3, count);
+ }
+ None => {
+ panic!(
+ "install_inference_counter: should have installed \\
+ CWILCallPolicy."
+ )
+ }
+ }
+ } else {
+ unreachable!()
}
- None => panic!(
- "install_inference_counter: should have installed \\
- CWILCallPolicy."
- ),
}
- }
_ => {
let stub = MachineError::functor_stub(
clause_name!("call_with_inference_limit"),
3,
);
- let type_error =
- self.error_form(MachineError::type_error(ValidType::Integer, a2), stub);
+
+ let type_error = self.error_form(
+ MachineError::type_error(
+ self.heap.h(),
+ ValidType::Integer,
+ a2,
+ ),
+ stub,
+ );
+
self.throw_exception(type_error)
}
};
}
&SystemClauseType::ModuleExists => {
- let module = self.store(self.deref(self[temp_v!(1)].clone()));
+ let module = self.store(self.deref(self[temp_v!(1)]));
match module {
- Addr::Con(Constant::Atom(ref name, _)) => {
- self.fail = !indices.modules.contains_key(name);
+ Addr::Con(h) => {
+ if let HeapCellValue::Atom(ref name, _) = &self.heap[h] {
+ self.fail = !indices.modules.contains_key(name);
+ } else {
+ unreachable!()
+ }
+ }
+ _ => {
+ unreachable!()
}
- _ => unreachable!()
};
}
&SystemClauseType::ModuleOf => {
- let module = self.store(self.deref(self[temp_v!(2)].clone()));
+ let module = self.store(self.deref(self[temp_v!(2)]));
match module {
- Addr::Con(Constant::Atom(name, _)) => {
- let module = Addr::Con(Constant::Atom(name.owning_module(), None));
- let target = self[temp_v!(1)].clone();
+ Addr::Con(h) if self.heap.atom_at(h) => {
+ if let HeapCellValue::Atom(name, _) = self.heap.clone(h) {
+ let module = self.heap.to_unifiable(
+ HeapCellValue::Atom(
+ name.owning_module(),
+ None
+ ),
+ );
- self.unify(target, module);
+ let target = self[temp_v!(1)];
+
+ self.unify(target, module);
+ } else {
+ unreachable!()
+ }
}
- Addr::Str(s) => match self.heap[s].clone() {
+ Addr::Str(s) => match self.heap.clone(s) {
HeapCellValue::NamedStr(_, name, ..) => {
- let module = Addr::Con(Constant::Atom(name.owning_module(), None));
+ let module = self.heap.to_unifiable(
+ HeapCellValue::Atom(
+ name.owning_module(),
+ None
+ ),
+ );
+
let target = self[temp_v!(1)].clone();
self.unify(target, module);
unreachable!()
}
},
- _ => self.fail = true,
+ _ => {
+ self.fail = true;
+ }
};
}
&SystemClauseType::NoSuchPredicate => {
- let head = self[temp_v!(1)].clone();
+ let head = self[temp_v!(1)];
self.fail = match self.store(self.deref(head)) {
- Addr::Str(s) => match self.heap[s].clone() {
- HeapCellValue::NamedStr(arity, name, op_spec) => {
+ Addr::Str(s) => match &self.heap[s] {
+ &HeapCellValue::NamedStr(arity, ref name, ref spec) => {
let module = name.owning_module();
- indices.predicate_exists(name, module, arity, op_spec)
+ indices.predicate_exists(name.clone(), module, arity, spec.clone())
+ }
+ _ => {
+ unreachable!()
}
- _ => unreachable!(),
},
- Addr::Con(Constant::Atom(name, spec)) => {
- let module = name.owning_module();
- let spec = fetch_atom_op_spec(name.clone(), spec, &indices.op_dir);
+ Addr::Con(h) if self.heap.atom_at(h) => {
+ if let &HeapCellValue::Atom(ref name, ref spec) = &self.heap[h] {
+ let module = name.owning_module();
+ let spec = fetch_atom_op_spec(name.clone(), spec.clone(), &indices.op_dir);
- indices.predicate_exists(name, module, 0, spec)
+ indices.predicate_exists(name.clone(), module, 0, spec)
+ } else {
+ unreachable!()
+ }
}
head => {
- let err = MachineError::type_error(ValidType::Callable, head);
+ let err = MachineError::type_error(self.heap.h(), ValidType::Callable, head);
let stub = MachineError::functor_stub(clause_name!("clause"), 2);
return Err(self.error_form(err, stub));
};
}
&SystemClauseType::RedoAttrVarBinding => {
- let var = self.store(self.deref(self[temp_v!(1)].clone()));
- let value = self.store(self.deref(self[temp_v!(2)].clone()));
+ let var = self.store(self.deref(self[temp_v!(1)]));
+ let value = self.store(self.deref(self[temp_v!(2)]));
match var {
Addr::AttrVar(h) => {
self.heap[h] = HeapCellValue::Addr(value);
}
}
- _ => unreachable!()
+ _ => {
+ unreachable!()
+ }
}
}
&SystemClauseType::ResetGlobalVarAtKey => {
- let key = self[temp_v!(1)].clone();
+ let key = self[temp_v!(1)];
- let key = match self.store(self.deref(key)) {
- Addr::Con(Constant::Atom(atom, _)) => atom,
- _ => unreachable!(),
- };
-
- indices.global_variables.swap_remove(&key);
+ match self.store(self.deref(key)) {
+ Addr::Con(h) if self.heap.atom_at(h) => {
+ if let HeapCellValue::Atom(ref key, _) = &self.heap[h] {
+ indices.global_variables.swap_remove(key);
+ } else {
+ unreachable!()
+ }
+ }
+ _ => {
+ unreachable!()
+ }
+ }
}
&SystemClauseType::ResetGlobalVarAtOffset => {
- let key = self[temp_v!(1)].clone();
+ let key = self[temp_v!(1)];
let key = match self.store(self.deref(key)) {
- Addr::Con(Constant::Atom(atom, _)) => atom,
- _ => unreachable!(),
+ Addr::Con(h) if self.heap.atom_at(h) => {
+ if let HeapCellValue::Atom(ref key, _) = &self.heap[h] {
+ key.clone()
+ } else {
+ unreachable!()
+ }
+ }
+ _ => {
+ unreachable!()
+ }
};
- let value = self[temp_v!(2)].clone();
+ let value = self[temp_v!(2)];
let mut ball = Ball::new();
- let h = self.heap.h();
- ball.boundary = h;
+ ball.boundary = self.heap.h();
+
copy_term(
CopyBallTerm::new(&mut self.stack, &mut self.heap, &mut ball.stub),
value,
AttrVarPolicy::DeepCopy,
);
- let offset = self[temp_v!(3)].clone();
+ let offset = self[temp_v!(3)];
match self.store(self.deref(offset)) {
- Addr::Con(Constant::Usize(offset)) => {
- indices.global_variables.insert(key, (ball, Some(offset)))
+ Addr::Usize(offset) => {
+ indices.global_variables.insert(key, (ball, Some(offset)));
}
_ => {
- indices.global_variables.insert(key, (ball, None))
+ indices.global_variables.insert(key, (ball, None));
}
- };
+ }
},
&SystemClauseType::ResetAttrVarState => {
self.attr_var_init.reset();
}
&SystemClauseType::RemoveCallPolicyCheck => {
- let restore_default = match call_policy.downcast_mut::<CWILCallPolicy>().ok() {
- Some(call_policy) => {
- let a1 = self.store(self.deref(self[temp_v!(1)].clone()));
-
- match a1 {
- Addr::Con(Constant::Usize(bp)) | Addr::Con(Constant::CutPoint(bp)) => {
- if call_policy.is_empty() && bp == self.b {
- Some(call_policy.into_inner())
- } else {
- None
+ let restore_default =
+ match call_policy.downcast_mut::<CWILCallPolicy>().ok() {
+ Some(call_policy) => {
+ let a1 = self.store(self.deref(self[temp_v!(1)]));
+
+ match a1 {
+ Addr::Usize(bp) | Addr::CutPoint(bp) => {
+ if call_policy.is_empty() && bp == self.b {
+ Some(call_policy.into_inner())
+ } else {
+ None
+ }
+ }
+ _ => {
+ panic!("remove_call_policy_check: expected Usize in A1.");
}
- }
- _ => {
- panic!("remove_call_policy_check: expected Usize in A1.");
}
}
- }
- None => panic!(
- "remove_call_policy_check: requires \\
- CWILCallPolicy."
- ),
- };
+ None => panic!(
+ "remove_call_policy_check: requires \\
+ CWILCallPolicy."
+ ),
+ };
if let Some(new_policy) = restore_default {
*call_policy = new_policy;
&SystemClauseType::RemoveInferenceCounter => {
match call_policy.downcast_mut::<CWILCallPolicy>().ok() {
Some(call_policy) => {
- let a1 = self.store(self.deref(self[temp_v!(1)].clone()));
+ let a1 = self.store(self.deref(self[temp_v!(1)]));
match a1 {
- Addr::Con(Constant::Usize(bp)) | Addr::Con(Constant::CutPoint(bp)) => {
+ Addr::Usize(bp) | Addr::CutPoint(bp) => {
let count = call_policy.remove_limit(bp);
- let count = Addr::Con(Constant::Integer(count.clone()));
+ let count = self.heap.to_unifiable(
+ HeapCellValue::Integer(Rc::new(count.clone())),
+ );
- let a2 = self[temp_v!(2)].clone();
+ let a2 = self[temp_v!(2)];
self.unify(a2, count);
}
),
}
}
- &SystemClauseType::REPL(repl_code_ptr) => return self.repl_redirect(repl_code_ptr),
+ &SystemClauseType::REPL(repl_code_ptr) => {
+ return self.repl_redirect(repl_code_ptr);
+ }
&SystemClauseType::ModuleRetractClause => {
let p = self.cp;
let trans_type = DynamicTransactionType::ModuleRetract;
let frame_len = self.stack.index_and_frame(e).prelude.univ_prelude.num_cells;
for i in 1 .. frame_len - 1 {
- self[RegType::Temp(i)] = self.stack.index_and_frame(e)[i].clone();
+ self[RegType::Temp(i)] = self.stack.index_and_frame(e)[i];
}
- if let &Addr::Con(Constant::CutPoint(b0)) = &self.stack.index_and_frame(e)[frame_len - 1] {
+ if let &Addr::CutPoint(b0) = &self.stack.index_and_frame(e)[frame_len - 1] {
self.b0 = b0;
}
- if let &Addr::Con(Constant::Usize(num_of_args)) = &self.stack.index_and_frame(e)[frame_len] {
+ if let &Addr::Usize(num_of_args) = &self.stack.index_and_frame(e)[frame_len] {
self.num_of_args = num_of_args;
}
deref_cut(self, r)
}
&SystemClauseType::SetInput => {
- let addr = self.store(self.deref(self[temp_v!(1)].clone()));
+ let addr = self.store(self.deref(self[temp_v!(1)]));
let stream = self.get_stream_or_alias(addr, indices, "set_input")?;
if stream.is_output_stream() {
- let stub = MachineError::functor_stub(clause_name!("set_input"), 1);
+ let stub = MachineError::functor_stub(
+ clause_name!("set_input"),
+ 1,
+ );
+
+ let user_alias = self.heap.to_unifiable(
+ HeapCellValue::Atom(clause_name!("user"), None),
+ );
+
let err = MachineError::permission_error(
- PermissionError::InputStream,
+ self.heap.h(),
+ Permission::InputStream,
"stream",
- Addr::Stream(stream),
+ user_alias,
);
return Err(self.error_form(err, stub));
}
-
+
*current_input_stream = stream;
}
&SystemClauseType::SetOutput => {
- let addr = self.store(self.deref(self[temp_v!(1)].clone()));
+ let addr = self.store(self.deref(self[temp_v!(1)]));
let stream = self.get_stream_or_alias(addr, indices, "set_output")?;
if stream.is_input_stream() {
- let stub = MachineError::functor_stub(clause_name!("set_input"), 1);
+ let stub = MachineError::functor_stub(
+ clause_name!("set_input"),
+ 1,
+ );
+
+ let user_alias = self.heap.to_unifiable(
+ HeapCellValue::Atom(clause_name!("user"), None),
+ );
+
let err = MachineError::permission_error(
- PermissionError::OutputStream,
+ self.heap.h(),
+ Permission::OutputStream,
"stream",
- Addr::Stream(stream),
+ user_alias,
);
return Err(self.error_form(err, stub));
*current_output_stream = stream;
}
- &SystemClauseType::SetDoubleQuotes => match self[temp_v!(1)].clone() {
- Addr::Con(Constant::Atom(ref atom, _)) if atom.as_str() == "chars" => {
- self.flags.double_quotes = DoubleQuotes::Chars
- }
- Addr::Con(Constant::Atom(ref atom, _)) if atom.as_str() == "atom" => {
- self.flags.double_quotes = DoubleQuotes::Atom
- }
- Addr::Con(Constant::Atom(ref atom, _)) if atom.as_str() == "codes" => {
- self.flags.double_quotes = DoubleQuotes::Codes
+ &SystemClauseType::SetDoubleQuotes => {
+ match self[temp_v!(1)] {
+ Addr::Con(h) if self.heap.atom_at(h) => {
+ if let HeapCellValue::Atom(ref atom, _) = &self.heap[h] {
+ self.flags.double_quotes =
+ match atom.as_str() {
+ "atom" => DoubleQuotes::Atom,
+ "chars" => DoubleQuotes::Chars,
+ "codes" => DoubleQuotes::Codes,
+ _ => {
+ self.fail = true;
+ return Ok(());
+ }
+ };
+ } else {
+ unreachable!()
+ }
+ }
+ _ => {
+ self.fail = true;
+ }
}
- _ => self.fail = true,
- },
+ }
&SystemClauseType::InferenceLevel => {
- let a1 = self[temp_v!(1)].clone();
- let a2 = self.store(self.deref(self[temp_v!(2)].clone()));
+ let a1 = self[temp_v!(1)];
+ let a2 = self.store(self.deref(self[temp_v!(2)]));
match a2 {
- Addr::Con(Constant::CutPoint(bp)) | Addr::Con(Constant::Usize(bp)) => {
+ Addr::CutPoint(bp) | Addr::Usize(bp) => {
let prev_b = self.stack.index_or_frame(self.b).prelude.b;
if prev_b <= bp {
- let a2 = Addr::Con(atom!("!"));
+ let a2 = self.heap.to_unifiable(
+ HeapCellValue::Atom(clause_name!("!"), None)
+ );
+
self.unify(a1, a2);
} else {
- let a2 = Addr::Con(atom!("true"));
+ let a2 = self.heap.to_unifiable(
+ HeapCellValue::Atom(clause_name!("true"), None)
+ );
+
self.unify(a1, a2);
}
}
- _ => self.fail = true,
- };
+ _ => {
+ self.fail = true;
+ }
+ }
}
&SystemClauseType::CleanUpBlock => {
- let nb = self.store(self.deref(self[temp_v!(1)].clone()));
+ let nb = self.store(self.deref(self[temp_v!(1)]));
match nb {
- Addr::Con(Constant::Usize(nb)) => {
+ Addr::Usize(nb) => {
let b = self.b;
if nb > 0 && self.stack.index_or_frame(b).prelude.b == nb {
self.b = self.stack.index_or_frame(nb).prelude.b;
}
}
- _ => self.fail = true,
+ _ => {
+ self.fail = true;
+ }
};
}
- &SystemClauseType::EraseBall => self.ball.reset(),
- &SystemClauseType::Fail => self.fail = true,
+ &SystemClauseType::EraseBall => {
+ self.ball.reset();
+ }
+ &SystemClauseType::Fail => {
+ self.fail = true;
+ }
&SystemClauseType::GetBall => {
- let addr = self.store(self.deref(self[temp_v!(1)].clone()));
+ let addr = self.store(self.deref(self[temp_v!(1)]));
let h = self.heap.h();
if self.ball.stub.h() > 0 {
}
&SystemClauseType::GetCurrentBlock => {
let c = Constant::Usize(self.block);
- let addr = self[temp_v!(1)].clone();
+ let addr = self[temp_v!(1)];
- self.write_constant_to_var(addr, c);
+ self.write_constant_to_var(addr, &c);
}
&SystemClauseType::GetBValue => {
- let a1 = self[temp_v!(1)].clone();
- let a2 = Addr::Con(Constant::Usize(self.b));
+ let a1 = self[temp_v!(1)];
+ let a2 = Addr::Usize(self.b);
self.unify(a1, a2);
}
&SystemClauseType::GetClause => {
- let head = self[temp_v!(1)].clone();
+ let head = self[temp_v!(1)];
let subsection = match self.store(self.deref(head)) {
- Addr::Str(s) => match self.heap[s].clone() {
- HeapCellValue::NamedStr(arity, name, ..) => {
- indices.get_clause_subsection(name.owning_module(), name, arity)
+ Addr::Str(s) => match &self.heap[s] {
+ &HeapCellValue::NamedStr(arity, ref name, ..) => {
+ indices.get_clause_subsection(
+ name.owning_module(),
+ name.clone(),
+ arity,
+ )
+ }
+ _ => {
+ unreachable!()
}
- _ => unreachable!(),
},
- Addr::Con(Constant::Atom(name, _)) => {
- indices.get_clause_subsection(name.owning_module(), name, 0)
+ Addr::Con(h) if self.heap.atom_at(h) => {
+ if let &HeapCellValue::Atom(ref name, _) = &self.heap[h] {
+ indices.get_clause_subsection(
+ name.owning_module(),
+ name.clone(),
+ 0,
+ )
+ } else {
+ unreachable!()
+ }
+ }
+ _ => {
+ unreachable!()
}
- _ => unreachable!(),
};
match subsection {
Some(dynamic_predicate_info) => {
self.execute_at_index(
2,
- dir_entry!(dynamic_predicate_info.clauses_subsection_p)
+ dir_entry!(dynamic_predicate_info.clauses_subsection_p),
);
+
return Ok(());
}
- _ => unreachable!(),
+ _ => {
+ unreachable!()
+ }
}
}
&SystemClauseType::GetCutPoint => {
- let a1 = self[temp_v!(1)].clone();
- let a2 = Addr::Con(Constant::CutPoint(self.b0));
+ let a1 = self[temp_v!(1)];
+ let a2 = Addr::CutPoint(self.b0);
self.unify(a1, a2);
}
ContinueResult::PrintWithMaxDepth => 'p',
};
- let target = self[temp_v!(1)].clone();
- self.unify(Addr::Con(Constant::Char(c)), target);
+ let target = self[temp_v!(1)];
+ self.unify(Addr::Char(c), target);
}
&SystemClauseType::NextEP => {
- let first_arg = self.store(self.deref(self[temp_v!(1)].clone()));
+ let first_arg = self.store(self.deref(self[temp_v!(1)]));
match first_arg {
- Addr::Con(Constant::Atom(ref name, _))
- if name.as_str() == "first" => {
- if self.e == 0 {
- self.fail = true;
- return Ok(());
- }
+ Addr::Con(h) if self.heap.atom_at(h) => {
+ if let HeapCellValue::Atom(ref name, _) = self.heap.clone(h) {
+ if name.as_str() == "first" {
+ if self.e == 0 {
+ self.fail = true;
+ return Ok(());
+ }
- let cp = (self.stack.index_and_frame(self.e).prelude.cp - 1).unwrap();
+ let cp = (self.stack.index_and_frame(self.e).prelude.cp - 1).unwrap();
- let e = self.stack.index_and_frame(self.e).prelude.e;
- let e = Addr::Con(Constant::Usize(e));
+ let e = self.stack.index_and_frame(self.e).prelude.e;
+ let e = Addr::Usize(e);
- let p = cp.as_functor(&mut self.heap);
+ let p = cp.as_functor(&mut self.heap);
- self.unify(self[temp_v!(2)].clone(), e);
+ self.unify(self[temp_v!(2)], e);
- if !self.fail {
- self.unify(self[temp_v!(3)].clone(), p);
+ if !self.fail {
+ self.unify(self[temp_v!(3)], p);
+ }
+ } else {
+ unreachable!()
}
- },
- Addr::Con(Constant::Usize(e)) => {
+ } else {
+ unreachable!()
+ }
+ }
+ Addr::Usize(e) => {
if e == 0 {
self.fail = true;
return Ok(());
let p = cp.as_functor(&mut self.heap);
let e = self.stack.index_and_frame(e).prelude.e;
- let e = Addr::Con(Constant::Usize(e));
+ let e = Addr::Usize(e);
- self.unify(self[temp_v!(2)].clone(), e);
+ self.unify(self[temp_v!(2)], e);
if !self.fail {
- self.unify(self[temp_v!(3)].clone(), p);
+ self.unify(self[temp_v!(3)], p);
}
}
- _ => unreachable!()
+ _ => {
+ unreachable!()
+ }
}
}
&SystemClauseType::PointsToContinuationResetMarker => {
- let addr = self.store(self.deref(self[temp_v!(1)].clone()));
+ let addr = self.store(self.deref(self[temp_v!(1)]));
let p = match self.heap.to_local_code_ptr(&addr) {
- Some(p) => p + 1,
+ Some(p) => {
+ p + 1
+ }
None => {
self.fail = true;
return Ok(());
return Ok(());
}
&SystemClauseType::QuotedToken => {
- let addr = self.store(self.deref(self[temp_v!(1)].clone()));
+ let addr = self.store(self.deref(self[temp_v!(1)]));
match addr {
- Addr::Con(Constant::CharCode(c)) => {
+ Addr::CharCode(c) => {
self.fail = match std::char::from_u32(c) {
Some(c) => {
non_quoted_token(once(c))
}
};
}
- Addr::Con(Constant::Char(c)) => {
+ Addr::Char(c) => {
self.fail = non_quoted_token(once(c));
}
- Addr::Con(Constant::Atom(atom, _)) => {
- self.fail = non_quoted_token(atom.as_str().chars());
+ Addr::Con(h) => {
+ if let HeapCellValue::Atom(atom, _) = &self.heap[h] {
+ self.fail = non_quoted_token(atom.as_str().chars());
+ }
}
_ => {
self.fail = true;
self.read_term(current_input_stream, indices)?;
}
&SystemClauseType::ResetBlock => {
- let addr = self.deref(self[temp_v!(1)].clone());
+ let addr = self.deref(self[temp_v!(1)]);
self.reset_block(addr);
}
&SystemClauseType::ResetContinuationMarker => {
- self[temp_v!(3)] = Addr::Con(Constant::Atom(clause_name!("none"), None));
-
let h = self.heap.h();
- self.heap.push(HeapCellValue::Addr(Addr::HeapCell(h)));
+ self[temp_v!(3)] = self.heap.to_unifiable(
+ HeapCellValue::Atom(clause_name!("none"), None)
+ );
+
+ self.heap.push(HeapCellValue::Addr(Addr::HeapCell(h)));
self[temp_v!(4)] = Addr::HeapCell(h);
}
- &SystemClauseType::SetBall =>
- self.set_ball(),
+ &SystemClauseType::SetBall => {
+ self.set_ball();
+ }
&SystemClauseType::SetSeed => {
- let seed = self.store(self.deref(self[temp_v!(1)].clone()));
+ let seed = self.store(self.deref(self[temp_v!(1)]));
let seed = match seed {
- Addr::Con(Constant::Integer(n)) =>
- n,
- Addr::Con(Constant::CharCode(c)) =>
- Integer::from(c),
- Addr::Con(Constant::Rational(r)) => {
- if r.denom() == &1 {
- r.numer().clone()
+ 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 {
- self.fail = true;
- return Ok(());
+ 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 {
+ self.fail = true;
+ return Ok(());
+ }
+ } else {
+ unreachable!()
}
}
_ => {
return Err(err);
},
&SystemClauseType::StoreGlobalVar => {
- let key = self[temp_v!(1)].clone();
+ let key = self[temp_v!(1)];
let key = match self.store(self.deref(key)) {
- Addr::Con(Constant::Atom(atom, _)) => atom,
- _ => unreachable!(),
+ Addr::Con(h) if self.heap.atom_at(h) => {
+ if let HeapCellValue::Atom(ref atom, _) = &self.heap[h] {
+ atom.clone()
+ } else {
+ unreachable!()
+ }
+ }
+ _ => {
+ unreachable!()
+ }
};
- let value = self[temp_v!(2)].clone();
+ let value = self[temp_v!(2)];
let mut ball = Ball::new();
ball.boundary = self.heap.h();
+
copy_term(
CopyBallTerm::new(&mut self.stack, &mut self.heap, &mut ball.stub),
value,
indices.global_variables.insert(key, (ball, None));
}
&SystemClauseType::StoreGlobalVarWithOffset => {
- let key = self[temp_v!(1)].clone();
+ let key = self[temp_v!(1)];
let key = match self.store(self.deref(key)) {
- Addr::Con(Constant::Atom(atom, _)) => atom,
- _ => unreachable!(),
+ Addr::Con(h) if self.heap.atom_at(h) => {
+ if let HeapCellValue::Atom(ref atom, _) = &self.heap[h] {
+ atom.clone()
+ } else {
+ unreachable!()
+ }
+ }
+ _ => {
+ unreachable!()
+ }
};
- let value = self[temp_v!(2)].clone();
+ let value = self[temp_v!(2)];
let mut ball = Ball::new();
let h = self.heap.h();
ball.boundary = h;
+
copy_term(
CopyBallTerm::new(&mut self.stack, &mut self.heap, &mut ball.stub),
value.clone(),
let stub = ball.copy_and_align(h);
self.heap.extend(stub.into_iter());
+
indices.global_variables.insert(key, (ball, Some(h)));
self.unify(value, Addr::HeapCell(h));
}
- &SystemClauseType::Succeed => {}
+ &SystemClauseType::Succeed => {
+ }
&SystemClauseType::TermVariables => {
- let a1 = self[temp_v!(1)].clone();
+ let a1 = self[temp_v!(1)];
let mut seen_vars = IndexSet::new();
- for item in self.acyclic_pre_order_iter(a1) {
- match item {
- HeapCellValue::Addr(addr) => {
- if addr.is_ref() {
- seen_vars.insert(addr);
- }
- }
- _ => {}
+ for addr in self.acyclic_pre_order_iter(a1) {
+ if addr.is_ref() {
+ seen_vars.insert(addr);
}
}
let outcome = Addr::HeapCell(self.heap.to_list(seen_vars.into_iter()));
- let a2 = self[temp_v!(2)].clone();
+ let a2 = self[temp_v!(2)];
self.unify(a2, outcome);
}
&SystemClauseType::TruncateLiftedHeapTo => {
- match self.store(self.deref(self[temp_v!(1)].clone())) {
- Addr::Con(Constant::Usize(lh_offset)) => self.lifted_heap.truncate(lh_offset),
- _ => self.fail = true,
+ match self.store(self.deref(self[temp_v!(1)])) {
+ Addr::Usize(lh_offset) =>
+ self.lifted_heap.truncate(lh_offset),
+ _ =>
+ self.fail = true,
}
}
&SystemClauseType::UnifyWithOccursCheck => {
- let a1 = self[temp_v!(1)].clone();
- let a2 = self[temp_v!(2)].clone();
+ let a1 = self[temp_v!(1)];
+ let a2 = self[temp_v!(2)];
self.unify_with_occurs_check(a1, a2);
}
e = self.stack.index_and_frame(e).prelude.e;
}
}
- &SystemClauseType::UnwindStack => self.unwind_stack(),
- &SystemClauseType::Variant => self.fail = self.structural_eq_test(),
+ &SystemClauseType::UnwindStack => {
+ self.unwind_stack();
+ }
+ &SystemClauseType::Variant => {
+ self.fail = self.structural_eq_test();
+ }
&SystemClauseType::WAMInstructions => {
- let name = self[temp_v!(1)].clone();
- let arity = self[temp_v!(2)].clone();
+ let name = self[temp_v!(1)];
+ let arity = self[temp_v!(2)];
let name = match self.store(self.deref(name)) {
- Addr::Con(Constant::Atom(name, _)) => name,
- _ => unreachable!(),
+ Addr::Con(h) if self.heap.atom_at(h) => {
+ if let HeapCellValue::Atom(ref atom, _) = &self.heap[h] {
+ atom.clone()
+ } else {
+ unreachable!()
+ }
+ }
+ _ => {
+ unreachable!()
+ }
};
let arity = match self.store(self.deref(arity)) {
- Addr::Con(Constant::Integer(n)) => n,
- _ => unreachable!(),
+ Addr::Con(h) if self.heap.integer_at(h) => {
+ if let HeapCellValue::Integer(ref n) = &self.heap[h] {
+ n.clone()
+ } else {
+ unreachable!()
+ }
+ }
+ _ => {
+ unreachable!()
+ }
};
let first_idx = match indices
h,
ExistenceError::Procedure(name, arity),
);
+
let err = self.error_form(err, stub);
self.throw_exception(err);
h,
ExistenceError::Procedure(name, arity),
);
+
let err = self.error_form(err, stub);
self.throw_exception(err);
self.unify(listing, listing_var);
}
&SystemClauseType::WriteTerm => {
- let addr = self[temp_v!(1)].clone();
+ let addr = self[temp_v!(1)];
- let ignore_ops = self.store(self.deref(self[temp_v!(2)].clone()));
- let numbervars = self.store(self.deref(self[temp_v!(3)].clone()));
- let quoted = self.store(self.deref(self[temp_v!(4)].clone()));
- let max_depth = self.store(self.deref(self[temp_v!(6)].clone()));
+ let ignore_ops = self.store(self.deref(self[temp_v!(2)]));
+ let numbervars = self.store(self.deref(self[temp_v!(3)]));
+ let quoted = self.store(self.deref(self[temp_v!(4)]));
+ let max_depth = self.store(self.deref(self[temp_v!(6)]));
let mut printer = HCPrinter::new(&self, &indices.op_dir, PrinterOutputter::new());
- if let &Addr::Con(Constant::Atom(ref name, ..)) = &ignore_ops {
- printer.ignore_ops = name.as_str() == "true";
+ if let &Addr::Con(h) = &ignore_ops {
+ if let HeapCellValue::Atom(ref name, _) = &self.heap[h] {
+ printer.ignore_ops = name.as_str() == "true";
+ } else {
+ unreachable!()
+ }
}
- if let &Addr::Con(Constant::Atom(ref name, ..)) = &numbervars {
- printer.numbervars = name.as_str() == "true";
+ if let &Addr::Con(h) = &numbervars {
+ if let HeapCellValue::Atom(ref name, _) = &self.heap[h] {
+ printer.numbervars = name.as_str() == "true";
+ } else {
+ unreachable!()
+ }
}
- if let &Addr::Con(Constant::Atom(ref name, ..)) = "ed {
- printer.quoted = name.as_str() == "true";
+ if let &Addr::Con(h) = "ed {
+ if let HeapCellValue::Atom(ref name, _) = &self.heap[h] {
+ printer.quoted = name.as_str() == "true";
+ } else {
+ unreachable!()
+ }
}
- if let &Addr::Con(Constant::Integer(ref n)) = &max_depth {
- if let Some(n) = n.to_usize() {
- printer.max_depth = n;
+ if let &Addr::Con(h) = &max_depth {
+ if let HeapCellValue::Integer(ref n) = &self.heap[h] {
+ if let Some(n) = n.to_usize() {
+ printer.max_depth = n;
+ } else {
+ self.fail = true;
+ return Ok(());
+ }
} else {
- self.fail = true;
- return Ok(());
+ unreachable!()
}
}
let stub = MachineError::functor_stub(clause_name!("write_term"), 2);
- match self.try_from_list(temp_v!(5), stub.clone()) {
+ match self.try_from_list(temp_v!(5), stub) {
Ok(addrs) => {
let mut var_names: IndexMap<Addr, String> = IndexMap::new();
let var = self.heap[s + 2].as_addr(s + 2);
let atom = match self.store(self.deref(atom)) {
- Addr::Con(Constant::Atom(atom, _)) => atom.to_string(),
- Addr::Con(Constant::Char(c)) => c.to_string(),
+ Addr::Con(h) => {
+ if let HeapCellValue::Atom(ref atom, _) = &self.heap[h] {
+ atom.to_string()
+ } else {
+ unreachable!()
+ }
+ }
+ Addr::Char(c) => c.to_string(),
_ => unreachable!(),
};
};
}
-macro_rules! heap_str {
- ($s:expr) => {
- HeapCellValue::Addr(Addr::Str($s))
- };
-}
-
-macro_rules! heap_integer {
- ($i:expr) => {
- HeapCellValue::Addr(Addr::Con(Constant::Integer($i)))
- };
-}
-
-macro_rules! heap_cell {
- ($i:expr) => {
- HeapCellValue::Addr(Addr::HeapCell($i))
- };
+/* A simple macro to count the arguments in a variadic list
+ * of token trees.
+ */
+macro_rules! count_tt {
+ () => { 0 };
+ ($odd:tt $($a:tt $b:tt)*) => { (count_tt!($($a)*) << 1) | 1 };
+ ($($a:tt $even:tt)*) => { count_tt!($($a)*) << 1 };
}
-macro_rules! heap_con {
- ($i:expr) => {
- HeapCellValue::Addr(Addr::Con($i))
- };
-}
+macro_rules! functor {
+ ($name:expr, $fixity:expr, [$($dt:ident($($value:expr),*)),+], [$($aux:ident),*]) => ({
+ {
+ #[allow(unused_variables, unused_mut)]
+ let mut addendum = Heap::new();
+ let arity = count_tt!($($dt) +);
+ let aux_lens = [$($aux.len()),*];
+
+ let mut result =
+ vec![ HeapCellValue::NamedStr(arity, clause_name!($name), Some($fixity)),
+ $(functor_term!( $dt($($value),*), arity, aux_lens, addendum ),)+ ];
+
+ $(
+ result.extend($aux.into_iter());
+ )*
+
+ result.extend(addendum.into_iter());
+ result
+ }
+ });
+ ($name:expr, $fixity:expr, [$($dt:ident($($value:expr),*)),+]) => ({
+ {
+ #[allow(unused_variables, unused_mut)]
+ let mut addendum = Heap::new();
+ let arity = count_tt!($($dt) +);
+
+ let mut result =
+ vec![ HeapCellValue::NamedStr(arity, clause_name!($name), Some($fixity)),
+ $(functor_term!( $dt($($value),*), arity, [], addendum ),)+ ];
+
+ result.extend(addendum.into_iter());
+ result
+ }
+ });
+ ($name:expr, [$($dt:ident($($value:expr),*)),+], [$($aux:ident),*]) => ({
+ {
+ #[allow(unused_variables, unused_mut)]
+ let mut addendum = Heap::new();
+ let arity = count_tt!($($dt) +);
+ let aux_lens = [$($aux.len()),*];
+
+ let mut result =
+ vec![ HeapCellValue::NamedStr(arity, clause_name!($name), None),
+ $(functor_term!( $dt($($value),*), arity, aux_lens, addendum ),)+ ];
+
+ $(
+ result.extend($aux.into_iter());
+ )*
+
+ result.extend(addendum.into_iter());
+ result
+ }
+ });
+ ($name:expr, [$($dt:ident($($value:expr),*)),+]) => ({
+ {
+ let arity = count_tt!($($dt) +);
-macro_rules! heap_atom {
- ($name:expr) => {
- HeapCellValue::Addr(Addr::Con(atom!($name)))
- };
- ($name:expr, $tbl:expr) => {
- HeapCellValue::Addr(Addr::Con(atom!($name, $tbl)))
- };
+ vec![ HeapCellValue::NamedStr(arity, clause_name!($name), None),
+ $(functor_term!( $dt($($value),*), arity, [], addendum ),)+ ]
+ }
+ });
+ ($name:expr, $fixity:expr) => (
+ vec![ HeapCellValue::Atom(clause_name!($name), Some($fixity)) ]
+ );
+ (clause_name($name:expr)) => (
+ vec![ HeapCellValue::Atom($name, None) ]
+ );
+ ($name:expr) => (
+ vec![ HeapCellValue::Atom(clause_name!($name), None) ]
+ );
}
-macro_rules! functor {
- ($name:expr) => (
- vec![ heap_atom!($name) ]
+macro_rules! functor_term {
+ (aux(0), $arity:expr, $aux_lens:expr, $addendum:ident) => ({
+ HeapCellValue::Addr(Addr::HeapCell($arity + 1))
+ });
+ (aux($e:expr), $arity:expr, $aux_lens:expr, $addendum:ident) => ({
+ let len: usize = $aux_lens[0 .. $e].iter().sum();
+ HeapCellValue::Addr(Addr::HeapCell($arity + 1 + len))
+ });
+ (aux($h:expr, 0), $arity:expr, $aux_lens:expr, $addendum:ident) => ({
+ HeapCellValue::Addr(Addr::HeapCell($arity + $h + 1))
+ });
+ (aux($h:expr, $e:expr), $arity:expr, $aux_lens:expr, $addendum:ident) => ({
+ let len: usize = $aux_lens[0 .. $e].iter().sum();
+ HeapCellValue::Addr(Addr::HeapCell($arity + $h + 1 + len))
+ });
+ (addr($e:expr), $arity:expr, $aux_lens:expr, $addendum:ident) => (
+ HeapCellValue::Addr($e)
+ );
+ (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)
+ );
+ (number($e:expr), $arity:expr, $aux_lens:expr, $addendum:ident) => (
+ $e.into()
+ );
+ /*
+ (string($s:expr), $arity:expr, $aux_lens:expr, $addendum: ident) => ({
+ let len: usize = $aux_lens.iter().sum();
+ let h = len + $arity + 1 + $addendum.h();
+
+ $addendum.allocate_pstr(&$s);
+
+ HeapCell::PStrLocation(h, 0)
+ });
+ */
+ (integer($e:expr), $arity:expr, $aux_lens:expr, $addendum: ident) => (
+ HeapCellValue::Integer(Rc::new(Integer::from($e)))
);
- ($name:expr, $len:expr) => (
- vec![ HeapCellValue::NamedStr($len, clause_name!($name), None) ]
+ (clause_name($e:expr), $arity:expr, $aux_lens:expr, $addendum: ident) => (
+ HeapCellValue::Atom($e, None)
);
- ($name:expr, $len:expr, [$($args:expr),*]) => (
- vec![ HeapCellValue::NamedStr($len, clause_name!($name), None), $($args),* ]
+ (atom($e:expr), $arity:expr, $aux_lens:expr, $addendum: ident) => (
+ HeapCellValue::Atom(clause_name!($e), None)
);
- ($name:expr, $len:expr, [$($args:expr),*], $fix: expr) => (
- vec![ HeapCellValue::NamedStr($len, clause_name!($name), Some($fix)), $($args),* ]
+ ($e:expr, $arity:expr, $aux_lens:expr, $addendum:ident) => (
+ $e
);
}
+macro_rules! from_constant {
+ ($e:expr, $over_h:expr, $arity:expr, $aux_lens:expr, $addendum:ident) => ({
+ match $e {
+ &Constant::Atom(ref name, ref op) => {
+ HeapCellValue::Atom(name.clone(), op.clone())
+ }
+ &Constant::Char(c) => {
+ HeapCellValue::Addr(Addr::Char(c))
+ }
+ &Constant::CharCode(c) => {
+ HeapCellValue::Addr(Addr::CharCode(c))
+ }
+ &Constant::CutPoint(cp) => {
+ HeapCellValue::Addr(Addr::CutPoint(cp))
+ }
+ &Constant::Integer(ref n) => {
+ HeapCellValue::Integer(n.clone())
+ }
+ &Constant::Rational(ref r) => {
+ HeapCellValue::Rational(r.clone())
+ }
+ &Constant::Float(f) => {
+ HeapCellValue::Addr(Addr::Float(f))
+ }
+ &Constant::String(ref s) => {
+ let len: usize = $aux_lens.iter().sum();
+ let h = len + $arity + 1 + $addendum.h() + $over_h;
+
+ $addendum.put_constant(Constant::String(s.clone()));
+
+ HeapCellValue::Addr(Addr::PStrLocation(h, 0))
+ }
+ &Constant::Usize(u) => {
+ HeapCellValue::Addr(Addr::Usize(u))
+ }
+ &Constant::EmptyList => {
+ HeapCellValue::Addr(Addr::EmptyList)
+ }
+ }
+ })
+}
+
macro_rules! is_atom {
($r:expr) => {
call_clause!(ClauseType::Inlined(InlinedClauseType::IsAtom($r)), 1, 0)
use crate::prolog::forms::*;
use crate::prolog::iterators::*;
+use crate::prolog::machine::heap::Heap;
use crate::prolog::machine::machine_indices::*;
use crate::prolog::machine::machine_state::MachineState;
use crate::prolog::machine::streams::Stream;
type SubtermDeque = VecDeque<(usize, usize)>;
impl<'a> TermRef<'a> {
- fn as_addr(&self, h: usize) -> Addr {
+ fn as_addr(&self, heap: &mut Heap, h: usize) -> Addr {
match self {
- &TermRef::AnonVar(_) | &TermRef::Var(..) => Addr::HeapCell(h),
- &TermRef::Cons(..) => Addr::HeapCell(h),
- &TermRef::Constant(_, _, c) => Addr::Con(c.clone()),
- &TermRef::Clause(..) => Addr::Str(h),
+ &TermRef::AnonVar(_) | &TermRef::Var(..) => {
+ Addr::HeapCell(h)
+ }
+ &TermRef::Cons(..) => {
+ Addr::HeapCell(h)
+ }
+ &TermRef::Constant(_, _, c) => {
+ heap.put_constant(c.clone())
+ }
+ &TermRef::Clause(..) => {
+ Addr::Str(h)
+ }
}
}
}
h: usize,
) {
if let Some((arity, site_h)) = queue.pop_front() {
- machine_st.heap[site_h] = HeapCellValue::Addr(term.as_addr(h));
+ machine_st.heap[site_h] = HeapCellValue::Addr(term.as_addr(&mut machine_st.heap, h));
if arity > 1 {
queue.push_front((arity - 1, site_h + 1));
}
}
&TermRef::AnonVar(Level::Root) | &TermRef::Constant(Level::Root, ..) => {
- machine_st.heap.push(HeapCellValue::Addr(term.as_addr(h)))
+ let value = HeapCellValue::Addr(term.as_addr(&mut machine_st.heap, h));
+ machine_st.heap.push(value);
}
&TermRef::Var(Level::Root, ..) => {
- machine_st.heap.push(HeapCellValue::Addr(term.as_addr(h)))
+ let value = HeapCellValue::Addr(term.as_addr(&mut machine_st.heap, h));
+ machine_st.heap.push(value);
}
&TermRef::AnonVar(_) => {
if let Some((arity, site_h)) = queue.pop_front() {
).
'$submit_query_and_print_results'(Term0, VarList) :-
+ write('oh brother'), nl,
( expand_goals(Term0, Term) -> true
; Term0 = Term
),
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
&HeapCellValue::Addr(ref addr) => write!(f, "{}", addr),
+ &HeapCellValue::Atom(ref atom, _) => write!(f, "{}", atom.as_str()),
+ &HeapCellValue::DBRef(ref db_ref) => write!(f, "{}", db_ref),
+ &HeapCellValue::Integer(ref n) => write!(f, "{}", n),
+ &HeapCellValue::Rational(ref n) => write!(f, "{}", n),
&HeapCellValue::NamedStr(arity, ref name, Some(ref cell)) => write!(
f,
"{}/{} (op, priority: {}, spec: {})",
write!(f, "{}/{}", name.as_str(), arity)
}
&HeapCellValue::PartialString(ref pstr) => {
- write!(f, "pstr ( buf: {} )", pstr.block_as_str())
+ write!(f, "pstr ( buf: 0x{:x} )", (pstr as *const _) as usize)
+ }
+ &HeapCellValue::Stream(ref stream) => {
+ write!(f, "$stream({})", stream.as_ptr() as usize)
}
}
}
impl fmt::Display for Addr {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
+ &Addr::Char(c) => write!(f, "Addr::Char({})", c),
+ &Addr::CharCode(c) => write!(f, "Addr::CharCode({})", c),
+ &Addr::EmptyList => write!(f, "Addr::EmptyList"),
+ &Addr::Float(fl) => write!(f, "Addr::Float({})", fl),
+ &Addr::CutPoint(cp) => write!(f, "Addr::CutPoint({})", cp),
&Addr::Con(ref c) => write!(f, "Addr::Con({})", c),
- &Addr::DBRef(ref db_ref) => write!(f, "Addr::DBRef({})", db_ref),
&Addr::Lis(l) => write!(f, "Addr::Lis({})", l),
&Addr::AttrVar(h) => write!(f, "Addr::AttrVar({})", h),
&Addr::HeapCell(h) => write!(f, "Addr::HeapCell({})", h),
&Addr::StackCell(fr, sc) => write!(f, "Addr::StackCell({}, {})", fr, sc),
&Addr::Str(s) => write!(f, "Addr::Str({})", s),
&Addr::PStrLocation(h, n) => write!(f, "Addr::PStrLocation({}, {})", h, n),
- &Addr::Stream(ref stream) => write!(f, "Addr::Stream({})", stream.as_ptr() as usize),
+ &Addr::Stream(stream) => write!(f, "Addr::Stream({})", stream),
+ &Addr::Usize(cp) => write!(f, "Addr::Usize({})", cp),
}
}
}