]> Repositorios git - scryer-prolog.git/commitdiff
harmonize partial strings with complete strings (#276), make Addr a copyable type
authorMark Thom <[email protected]>
Fri, 3 Apr 2020 16:22:46 +0000 (10:22 -0600)
committerMark Thom <[email protected]>
Fri, 3 Apr 2020 16:22:46 +0000 (10:22 -0600)
33 files changed:
Cargo.lock
Cargo.toml
src/prolog/forms.rs
src/prolog/heap_iter.rs
src/prolog/heap_print.rs
src/prolog/instructions.rs
src/prolog/lib/atts.pl
src/prolog/lib/builtins.pl
src/prolog/lib/cont.pl
src/prolog/lib/tabling.pl
src/prolog/lib/tabling/double_linked_list.pl
src/prolog/lib/tabling/global_worklist.pl
src/prolog/lib/tabling/trie.pl
src/prolog/machine/arithmetic_ops.rs
src/prolog/machine/attributed_variables.pl
src/prolog/machine/attributed_variables.rs
src/prolog/machine/copier.rs
src/prolog/machine/dynamic_database.rs
src/prolog/machine/heap.rs
src/prolog/machine/machine_errors.rs
src/prolog/machine/machine_indices.rs
src/prolog/machine/machine_state.rs
src/prolog/machine/machine_state_impl.rs
src/prolog/machine/partial_string.rs
src/prolog/machine/raw_block.rs
src/prolog/machine/stack.rs
src/prolog/machine/system_calls.rs
src/prolog/machine/term_expansion.rs
src/prolog/macros.rs
src/prolog/read.rs
src/prolog/toplevel.pl
src/prolog/write.rs
src/tests/facts.pl

index 0fe6e3f4cfa52e4504fe399eea7c67c56e000762..ea022e957687c708d786a0efb3a70669c32c3b01 100644 (file)
@@ -445,6 +445,7 @@ dependencies = [
 [[package]]
 name = "prolog_parser"
 version = "0.8.48"
+source = "registry+https://github.com/rust-lang/crates.io-index"
 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)",
@@ -579,7 +580,7 @@ dependencies = [
  "nix 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "num-rug-adapter 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "ordered-float 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "prolog_parser 0.8.48",
+ "prolog_parser 0.8.48 (registry+https://github.com/rust-lang/crates.io-index)",
  "ref_thread_local 0.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "rug 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustyline 6.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -790,6 +791,7 @@ dependencies = [
 "checksum parking_lot 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "92e98c49ab0b7ce5b222f2cc9193fc4efe11c6d0bd4f648e374684a6857b1cfc"
 "checksum parking_lot_core 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7582838484df45743c8434fbff785e8edf260c28748353d44bc0da32e0ceabf1"
 "checksum proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)" = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759"
+"checksum prolog_parser 0.8.48 (registry+https://github.com/rust-lang/crates.io-index)" = "301d67e5905691f8d5dc5f08c8c6e12cf849a12bea779af8b5221c35b89faf95"
 "checksum quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)" = "6ce23b6b870e8f94f81fb0a363d65d86675884b34a09043c81e5562f11c1f8e1"
 "checksum rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b"
 "checksum rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc"
index 7c3338f3bcd7cd4c2f3617ed5feae526832ffcc6..b8a576235f2bf0e820e5ad346b2495273c7f3b9e 100644 (file)
@@ -25,10 +25,7 @@ libc = "0.2.62"
 nix = "0.15.0"
 num-rug-adapter = { optional = true, version = "0.1.1" }
 ordered-float = "0.5.0"
-prolog_parser = { version = "0.8.48", path = "../prolog_parser", default-features = false }
+prolog_parser = { version = "0.8.48", default-features = false }
 ref_thread_local = "0.0.0"
 rug = { version = "1.4.0", optional = true }
-rustyline = "6.0.0"
-
-[profile.release]
-debug = true
\ No newline at end of file
+rustyline = "6.0.0"
\ No newline at end of file
index 4f56922712730f1bdf3bef3a69fe6c02c363c3ca..f26361deda2e57e29d08d88f8d463c58fe884fcf 100644 (file)
@@ -282,9 +282,9 @@ impl ClauseConsistency for Rule {
     fn name_and_module(&self) -> Option<(ClauseName, ClauseName)> {
         Some((self.head.0.owning_module(), self.head.0.clone()))
     }
-    
+
     fn arity(&self) -> usize {
-        self.head.1.len()    
+        self.head.1.len()
     }
 }
 
@@ -597,7 +597,7 @@ impl Into<HeapCellValue> for Number {
     }
 }
 
-impl Number {    
+impl Number {
     #[inline]
     pub fn is_positive(&self) -> bool {
         match self {
index 57434fd93458f1c01036cd7f1062d93f82cd31ac..8a3ce4926b6c6eb34f214c7648491b17534895f8 100644 (file)
@@ -37,7 +37,7 @@ impl<'a> HCPreOrderIterator<'a> {
             &HeapCellValue::Addr(a) => {
                 self.follow(a)
             }
-            HeapCellValue::PartialString(_) => {
+            HeapCellValue::PartialString(..) => {
                 self.follow(Addr::PStrLocation(h, 0))
             }
             HeapCellValue::Atom(..) | HeapCellValue::DBRef(_)
@@ -64,17 +64,19 @@ impl<'a> HCPreOrderIterator<'a> {
                 da
             }
             Addr::PStrLocation(h, n) => {
-                if let HeapCellValue::PartialString(ref pstr) = &self.machine_st.heap[h] {
+                if let &HeapCellValue::PartialString(ref pstr, has_tail) = &self.machine_st.heap[h] {
                     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 {
+                        } else if has_tail {
                             self.state_stack.push(Addr::HeapCell(h + 1));
+                        } else {
+                            self.state_stack.push(Addr::EmptyList);
                         }
 
                         self.state_stack.push(Addr::Char(c));
-                    } else {
-                        unreachable!()
+                    } else if has_tail {
+                        return self.follow(Addr::HeapCell(h + 1));
                     }
                 } else {
                     unreachable!()
@@ -86,8 +88,19 @@ impl<'a> HCPreOrderIterator<'a> {
                 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));
+                if let &HeapCellValue::PartialString(ref pstr, has_tail) = &self.machine_st.heap[h] {
+                    if !self.machine_st.flags.double_quotes.is_atom() {
+                        return if let Some(c) = pstr.range_from(0 ..).next() {
+                            self.state_stack.push(Addr::PStrLocation(h, c.len_utf8()));
+                            self.state_stack.push(Addr::Char(c));
+
+                            Addr::PStrLocation(h, 0)
+                        } else if has_tail {
+                            self.follow(Addr::HeapCell(h + 1))
+                        } else {
+                            Addr::EmptyList
+                        };
+                    }
                 }
 
                 Addr::Con(h)
@@ -157,11 +170,18 @@ impl<'a> Iterator for HCPostOrderIterator<'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!()
+                        match &self.machine_st.heap[h] {
+                            &HeapCellValue::PartialString(ref pstr, _) => {
+                                let c = pstr.range_from(n ..).next().unwrap();
+                                let next_n = n + c.len_utf8();
+
+                                if !pstr.at_end(next_n) {
+                                    self.parent_stack.push((2, Addr::PStrLocation(h, next_n)));
+                                }
+                            }
+                            _ => {
+                                unreachable!()
+                            }
                         }
                     }
                     _ => {
index 0ccc155b732be67afa4195948d1fee9a4c815279..036597522c0c68aaf4f32b5913b0e5252c0a9ff5 100644 (file)
@@ -184,16 +184,16 @@ pub trait HCValueOutputter {
     type Output;
 
     fn new() -> Self;
-    fn push_char(&mut self, _: char);
-    fn append(&mut self, _: &str);
+    fn push_char(&mut self, c: char);
+    fn append(&mut self, s: &str);
     fn begin_new_var(&mut self);
-    fn insert(&mut self, _: usize, _: char);
+    fn insert(&mut self, index: usize, c: char);
     fn result(self) -> Self::Output;
-    fn ends_with(&self, _: &str) -> bool;
+    fn ends_with(&self, s: &str) -> bool;
     fn len(&self) -> usize;
-    fn truncate(&mut self, _: usize);
-    fn range(&self, _: Range<usize>) -> &str;
-    fn range_from(&self, _: RangeFrom<usize>) -> &str;
+    fn truncate(&mut self, len: usize);
+    fn range(&self, range: Range<usize>) -> &str;
+    fn range_from(&self, range: RangeFrom<usize>) -> &str;
 }
 
 pub struct PrinterOutputter {
@@ -1022,130 +1022,149 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
         }
     }
 
-    fn print_string_as_str(
-        &mut self,
-        mut h: usize,
-        mut offset: usize,
-        quoted: bool,
-    ) {
-        self.push_char('"');
-
-        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;
-        }
-
-        self.push_char('"');
-    }
-
     fn print_string(
         &mut self,
+        iter: &mut HCPreOrderIterator,
         mut max_depth: usize,
-        mut h: usize,
-        mut offset: usize,
+        h: usize,
+        n: 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))
-                        };
+        iter.stack().pop();
+        iter.stack().pop();
 
-                    let mut char_count = 0;
-                    let mut byte_len = 0;
+        if self.check_max_depth(&mut max_depth) {
+            self.state_stack.push(TokenOrRedirect::Atom(clause_name!("...")));
+            return;
+        }
 
-                    for c in iter {
-                        self.print_char(self.quoted, '.');
-                        self.push_char('(');
+        let mut heap_pstr_iter =
+            self.machine_st.heap_pstr_iter(Addr::PStrLocation(h, n));
 
-                        self.print_char(self.quoted, c);
-                        self.push_char(',');
+        let mut buf = String::new();
 
-                        char_count += 1;
-                        byte_len += c.len_utf8();
-                    }
+        while let Some(Some(c)) = heap_pstr_iter.next() {
+            buf.push(c);
+        }
 
-                    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;
+        let end_addr =
+            if let &HeapCellValue::PartialString(_, has_tail) = &self.machine_st.heap[h] {
+                if has_tail {
+                    self.machine_st.store(self.machine_st.deref(heap_pstr_iter.focus()))
+                } else {
+                    Addr::EmptyList
+                }
+            } else {
+                unreachable!()
+            };
+
+        if let Addr::EmptyList = end_addr {
+            if !self.machine_st.flags.double_quotes.is_codes() {
+                self.push_char('"');
+
+                let buf =
+                    if max_depth == 0 {
+                        String::from_iter(buf.chars().map(|c| {
+                            char_to_string(self.quoted, c)
+                        }))
+                    } else {
+                        let mut char_count = 0;
+                        let mut buf =
+                            String::from_iter(buf.chars().take(max_depth).map(|c| {
+                                char_count += 1;
+                                char_to_string(self.quoted, c)
+                            }));
+
+                        if char_count == max_depth {
+                            buf += " ...";
                         }
-                    }
 
-                    for _ in 0 .. char_count {
-                        self.push_char(')');
-                    }
+                        buf
+                    };
 
-                    if at_end {
-                        break;
-                    }
+                self.append_str(&buf);
+                self.push_char('"');
 
-                    max_depth -= char_count;
-                } else {
-                    self.push_char('[');
+                return;
+            }
+        }
 
-                    let iter: Box<dyn Iterator<Item=char>> =
-                        if self.max_depth == 0 {
-                            Box::new(pstr.range_from(offset ..))
-                        } else {
-                            Box::new(pstr.range_from(offset ..).take(max_depth))
-                        };
+        let buf_len = buf.len();
 
-                    let mut byte_len = 0;
-                    let mut char_count = 0;
+        let buf_iter: Box<dyn Iterator<Item=char>> =
+            if self.max_depth == 0 {
+                Box::new(buf.chars())
+            } else {
+                Box::new(buf.chars().take(max_depth))
+            };
 
-                    for c in iter {
-                        self.print_char(false, c);
-                        self.push_char(',');
+        let mut byte_len = 0;
 
-                        byte_len += c.len_utf8();
-                        char_count += 1;
-                    }
+        let char_printer = |printer: &mut Self, c| {
+            if printer.machine_st.flags.double_quotes.is_codes() {
+                let s = (c as u32).to_string();
 
-                    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(']');
-                    }
+                push_space_if_amb!(printer, &s, {
+                    printer.append_str(&s);
+                });
+            } else {
+                printer.print_char(printer.quoted, c);
+            }
+        };
 
-                    max_depth -= char_count;
-                }
+        if self.ignore_ops {
+            let mut char_count = 0;
+
+            for c in buf_iter {
+                self.push_char('.');
+                self.push_char('(');
+
+                char_printer(self, c);
+                self.push_char(',');
+
+                char_count += 1;
+                byte_len += c.len_utf8();
+            }
+
+            for _ in 0 .. char_count {
+                self.state_stack.push(TokenOrRedirect::Close);
+            }
 
-                h += 2;
-                offset = 0;                
+            if self.max_depth > 0 && buf_len > byte_len {
+                self.state_stack.push(TokenOrRedirect::Atom(clause_name!("...")));
+            } else {
+                self.state_stack.push(TokenOrRedirect::FunctorRedirect(max_depth));
+                iter.stack().push(end_addr);
             }
         } else {
-            self.print_string_as_str(h, 0, self.quoted);
+            let switch = if !self.at_cdr(",") {
+                self.push_char('[');
+                true
+            } else {
+                false
+            };
+
+            for c in buf_iter {
+                char_printer(self, c);
+                self.push_char(',');
+
+                byte_len += c.len_utf8();
+            }
+
+            self.state_stack.push(TokenOrRedirect::CloseList(Rc::new(
+                Cell::new((switch, 0))
+            )));
+
+            if self.max_depth > 0 && buf_len > byte_len {
+                self.state_stack.push(TokenOrRedirect::Atom(clause_name!("...")));
+            }  else {
+                self.outputter.truncate(self.outputter.len() - ','.len_utf8());
+                self.state_stack.push(TokenOrRedirect::FunctorRedirect(max_depth));
+
+                iter.stack().push(end_addr);
+            }
+
+            self.state_stack.push(TokenOrRedirect::HeadTailSeparator);
         }
     }
 
@@ -1250,7 +1269,7 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
             Some(addr) => addr,
             None => return,
         };
-        
+
         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);
@@ -1320,23 +1339,8 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
             &HeapCellValue::Addr(Addr::Usize(u)) => {
                 self.append_str(&format!("{}", u));
             }
-            &HeapCellValue::Addr(Addr::PStrLocation(..))
-                if !self.machine_st.flags.double_quotes.is_atom() => {
-                    if self.ignore_ops {
-                        self.format_struct(iter, max_depth, 2, clause_name!("."));
-                    } else {
-                        self.push_list(iter, max_depth);
-                    }
-                }
             &HeapCellValue::Addr(Addr::PStrLocation(h, n)) => {
-                if let HeapCellValue::PartialString(_) = &self.machine_st.heap[h] {
-                    self.print_string(max_depth, h, n);
-
-                    iter.stack().pop();
-                    iter.stack().pop();
-                } else {
-                    unreachable!()
-                }
+                self.print_string(iter, max_depth, h, n);
             }
             &HeapCellValue::Addr(Addr::Lis(_)) => {
                 if self.ignore_ops {
@@ -1358,21 +1362,6 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
             &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);
@@ -1385,6 +1374,7 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
                 }
             }
             _ => {
+                unreachable!()
             }
         }
     }
index eb6db521f9aeb970bbc9f53f43f48b1bfaaa049f..903fbd3cf17759e84e65bd9432b831aa8d6ef1d9 100644 (file)
@@ -482,7 +482,7 @@ impl FactInstruction {
                 
                 functor!(
                     "get_constant",
-                    [aux(h, 0), constant(c), aux(h, 1)],
+                    [aux(h, 0), constant(h, c), aux(h, 1)],
                     [lvl_stub, rt_stub]
                 )
             }
@@ -524,7 +524,7 @@ impl FactInstruction {
                 )
             }
             &FactInstruction::UnifyConstant(ref c) => {
-                functor!("unify_constant", [constant(c)], [])
+                functor!("unify_constant", [constant(h, c)], [])
             }
             &FactInstruction::UnifyLocalValue(r) => {
                 let rt_stub = reg_type_into_functor(r);
@@ -589,7 +589,7 @@ impl QueryInstruction {
 
                 functor!(
                     "put_constant",
-                    [aux(h, 0), constant(c), aux(h, 1)],
+                    [aux(h, 0), constant(h, c), aux(h, 1)],
                     [lvl_stub, rt_stub]
                 )
             }
@@ -640,7 +640,7 @@ impl QueryInstruction {
                 )
             }
             &QueryInstruction::SetConstant(ref c) => {
-                functor!("set_constant", [constant(c)], [])
+                functor!("set_constant", [constant(h, c)], [])
             }
             &QueryInstruction::SetLocalValue(r) => {
                 let rt_stub = reg_type_into_functor(r);
index 1522e0ce1a8b0d7ce4922ffea06adf3dc071d68a..1d6fddf7d6e9a0eb84b904216f82239fff8cc798 100644 (file)
@@ -132,11 +132,11 @@ put_attr(Name, Arity) -->
                            '$put_attr'(V, Attr)),
      (put_atts(V,  Attr) :- !, functor(Attr, Head, Arity),
                            functor(AttrForm, Head, Arity),
-                           '$get_attr_list'(V, Ls), 
-                           '$del_attr'(Ls, V, AttrForm), 
+                           '$get_attr_list'(V, Ls),
+                           '$del_attr'(Ls, V, AttrForm),
                            '$put_attr'(V, Attr)),
      (put_atts(V, -Attr) :- !, functor(Attr, _, _),
-                           '$get_attr_list'(V, Ls), 
+                           '$get_attr_list'(V, Ls),
                            '$del_attr'(Ls, V, Attr))].
 
 get_attr(Name, Arity) -->
@@ -158,4 +158,3 @@ call_residue_vars(Goal, Vars) :-
     '$get_attr_var_queue_delim'(B),
     call(Goal),
     '$get_attr_var_queue_beyond'(B, Vars).
-    
index 352a18a96ba8786799617387c2c5e53eaad42d35..cff33c7773778f0ed1775177c4477333876de4bc 100644 (file)
@@ -262,8 +262,11 @@ univ_errors(Term, List, N) :-
 Term =.. List :- '$call_with_default_policy'(univ_errors(Term, List, N)),
                 '$call_with_default_policy'(univ_worker(Term, List, N)).
 
+
 :- non_counted_backtracking univ_worker/3.
-univ_worker(Term, List, _) :- atomic(Term), !, '$call_with_default_policy'(List = [Term]).
+
+univ_worker(Term, List, _) :-
+    atomic(Term), !, '$call_with_default_policy'(List = [Term]).
 univ_worker(Term, [Name|Args], N) :-
     var(Term), !,
     '$call_with_default_policy'(Arity is N-1),
@@ -274,7 +277,9 @@ univ_worker(Term, List, _) :-
     '$call_with_default_policy'(get_args(Args, Term, 1, Arity)),
     '$call_with_default_policy'(List = [Name|Args]).
 
+
 :- non_counted_backtracking get_args/4.
+
 get_args(Args, _, _, 0) :-
     !, '$call_with_default_policy'(Args = []).
 get_args([Arg], Func, N, N) :-
@@ -287,19 +292,19 @@ get_args([Arg|Args], Func, I0, N) :-
 % write, write_canonical, writeq, write_term.
 is_write_option(Functor) :-
     Functor =.. [Name, Arg],
-    ( Arg == true -> true
-    ; Arg == false -> true
-    ; Name == variable_names -> must_be_var_names_list(Arg)
-    ; Name == max_depth -> integer(Arg), Arg >= 0
-    ; var(Arg) -> throw(error(instantiation_error, write_term/2))
-    ; throw(error(domain_error(write_option, Functor), write_term/2))
+    (  Arg == true -> true
+    ;  Arg == false -> true
+    ;  Name == variable_names -> must_be_var_names_list(Arg)
+    ;  Name == max_depth -> integer(Arg), Arg >= 0
+    ;  var(Arg) -> throw(error(instantiation_error, write_term/2))
+    ;  throw(error(domain_error(write_option, Functor), write_term/2))
     ), % 8.14.2.3 e)
-    ( Name == ignore_ops -> true
-    ; Name == quoted -> true
-    ; Name == numbervars -> true
-    ; Name == variable_names -> true
-    ; Name == max_depth -> true
-    ; throw(error(domain_error(write_option, Functor), write_term/2))
+    (  Name == ignore_ops -> true
+    ;  Name == quoted -> true
+    ;  Name == numbervars -> true
+    ;  Name == variable_names -> true
+    ;  Name == max_depth -> true
+    ;  throw(error(domain_error(write_option, Functor), write_term/2))
     ). % 8.14.2.3 e)
 
 inst_member_or([X|Xs], Y, Z) :-
index 18d97005e2222758caf99ed6d251d7c7c7a78ee7..032234e6d5b8e23cada0dc8b378ebca07104d251 100644 (file)
@@ -1,4 +1,3 @@
-
 :- module(cont, [reset/3, shift/1]).
 
 reset(Goal, Ball, Cont) :-
@@ -7,14 +6,14 @@ reset(Goal, Ball, Cont) :-
     '$bind_from_register'(Cont, 3),
     '$bind_from_register'(Ball, 4).
 
-shift(Term) :-
+shift(Ball) :-
     '$nextEP'(first, E, P),
     get_chunks(E, P, L),
     (  L == [] ->
        Cont = none
     ;  Cont = cont(call_continuation(L))
     ),
-    '$write_cont_and_term'(_, _, Cont, Term),
+    '$write_cont_and_term'(_, _, Cont, Ball),
     '$unwind_environments'.
 
 get_chunks(E, P, L) :-
index 0c2aa766d2d001b60f7ef7a4de0cdfc38176d080..153d7f47070c964c7c01e06c856148acd87164b2 100644 (file)
@@ -135,7 +135,7 @@ activate(Wrapper,Worker,T) :-
 
 delim(Wrapper,Worker,Table) :-
 %   debug(tabling, 'ACT: ~p on ~p', [Wrapper, Table]),
-   reset(Worker,SourceCall,Continuation),
+    reset(Worker,SourceCall,Continuation),
    ( Continuation == none, var(SourceCall) ->
      (  add_answer(Table,Wrapper)
      ->         true %debug(tabling, 'ADD: ~p', [Wrapper])
@@ -144,9 +144,9 @@ delim(Wrapper,Worker,Table) :-
      )
    ;
      (   Continuation = cont(Cont) ->
-        true
+            true
      ;   Continuation = none ->
-        Cont = true
+            Cont = true
      ),
      SourceCall = call_info(_,SourceTable),
      TargetCall = call_info(Wrapper,Table),
@@ -178,7 +178,7 @@ completion_step(SourceTableID) :-
     fail
   ;
     true
-  ).  
+  ).
 
 table_get_work(NBWorklistID,Answer,Dependency) :-
   % get_worklist(Table, Worklist),
@@ -192,7 +192,7 @@ table_get_work(NBWorklistID,Answer,Dependency) :-
 table_get_work_(NBWorklistID,Answer,Dependency) :-
   worklist_do_all_work(NBWorklistID,Answer,Dependency0), % This will eventually fail
   copy_term(Dependency0,Dependency).
-  
+
 table_get_work_(NBWorklistID,_Answer,_Dependency) :-
   bb_get(NBWorklistID, table_nb_worklist(Worklist)),
   unset_flag_executing_all_work(Worklist),
index 4cd1aab3dd5f3c4c5e0afae3a761c3df9973544b..d80ee6db63fb746724b855ae2a015781bd4f3a78 100644 (file)
@@ -208,4 +208,3 @@ dll_get_reverse_contents_(List, Contents) :-
        dll_get_pointer_to_previous(List, Prev),
        dll_get_reverse_contents_(Prev, Rest)
     ).
-
index dbe8b4c5998a44a98229bb1794e1e28b71ca6a60..19502a92ea52382dee9e8f9b03f6d610b59b5549 100644 (file)
@@ -1,4 +1,4 @@
-/*    Ported to Scryer Prolog by Mark Thom (2019/2020). 
+/*    Ported to Scryer Prolog by Mark Thom (2019/2020).
  */
 
 :- module(global_worklist,
@@ -21,7 +21,7 @@ put_new_global_worklist :-
      bb_b_put(table_global_worklist_initialized, [])
   ).
 
-add_to_global_worklist(TableIdentifier) :-  
+add_to_global_worklist(TableIdentifier) :-
   bb_get(table_global_worklist, TableGlobalWorklistFlag),
   get_atts(TableGlobalWorklistFlag, table_global_worklist(L1)),
   put_atts(TableGlobalWorklistFlag, table_global_worklist([TableIdentifier|L1])),
@@ -34,7 +34,7 @@ worklist_empty :-
 
 pop_worklist(TableIdentifier) :-
   bb_get(table_global_worklist,TableGlobalWorklistFlag),
-  get_atts(TableGlobalWorklistFlag, table_global_worklist(L1)),  
+  get_atts(TableGlobalWorklistFlag, table_global_worklist(L1)),
   L1 = [TableIdentifier|L2],
   put_atts(TableGlobalWorklistFlag, table_global_worklist(L2)),
   bb_put(table_global_worklist, TableGlobalWorklistFlag).
index eb102df12e2c6eb8ee97d4b0e918476f7771fb2c..18e77d9f3ac50997a099a0b5acbb04f66fdda435 100644 (file)
@@ -187,7 +187,7 @@ trie_insert_1_1_1(>,_V,_L,R,Assoc,FunctorData,Trie,First,Rest,Value) :-
   % Look in the right part of the assoc tree.
   trie_insert_1_1(R,Assoc,FunctorData,Trie,First,Rest,Value).
 
-trie_insert_2(RegularTerm,Rest,Trie,Value) :-  
+trie_insert_2(RegularTerm,Rest,Trie,Value) :-
   p_trie_arity_univ(RegularTerm,FunctorData,KList),
   append(KList,Rest,KList2),
   trie_insert_1(KList2,FunctorData,Trie,Value).
index 647c88b84043640054aff467305fb0415a065734..cf2a3b9187d18629ce172f9282faf35ae44b7cc7 100644 (file)
@@ -175,6 +175,12 @@ impl MachineState {
                 &HeapCellValue::Addr(Addr::Float(n)) => {
                     interms.push(Number::Float(n))
                 }
+                &HeapCellValue::Addr(Addr::Usize(n)) => {
+                    interms.push(Number::Integer(Rc::new(Integer::from(n))));
+                }
+                &HeapCellValue::Addr(Addr::CharCode(n)) => {
+                    interms.push(Number::Integer(Rc::new(Integer::from(n))));
+                }
                 &HeapCellValue::Rational(ref n) => {
                     interms.push(Number::Rational(n.clone()))
                 }
index 2a18d639594742d1d07085dc4d25d57b275c29af..af8d8af8a6e76050d12d1c346c4ef2430765943b 100644 (file)
@@ -21,13 +21,13 @@ call_verify_attributes(Attrs, _, _, []) :-
 call_verify_attributes([], _, _, []).
 call_verify_attributes([Attr|Attrs], Var, Value, ListOfGoalLists) :-
     gather_modules([Attr|Attrs], Modules0),
-    sort(Modules0, Modules),    
+    sort(Modules0, Modules),
     verify_attrs(Modules, Var, Value, ListOfGoalLists).
 
 verify_attrs([Module|Modules], Var, Value, [Goals|ListOfGoalLists]) :-
     catch(Module:verify_attributes(Var, Value, Goals),
           error(evaluation_error((Module:verify_attributes)/3), verify_attributes/3),
-          Goals = []),    
+          Goals = []),
     verify_attrs(Modules, Var, Value, ListOfGoalLists).
 verify_attrs([], _, _, []).
 
index f21c892652671e922039fd3d1d3f3fff3c7f4393..b216a48caac0213c70a10287c7f93c949a652d99 100644 (file)
@@ -19,7 +19,8 @@ pub(super) struct AttrVarInitializer {
 }
 
 impl AttrVarInitializer {
-    pub(super) fn new(verify_attrs_loc: usize, project_attrs_loc: usize) -> Self {
+    pub(super)
+    fn new(verify_attrs_loc: usize, project_attrs_loc: usize) -> Self {
         AttrVarInitializer {
             attribute_goals: vec![],
             attr_var_queue: vec![],
@@ -32,21 +33,24 @@ impl AttrVarInitializer {
     }
 
     #[inline]
-    pub(super) fn reset(&mut self) {
-       self.attribute_goals.clear();
+    pub(super)
+    fn reset(&mut self) {
+           self.attribute_goals.clear();
         self.attr_var_queue.clear();
         self.bindings.clear();
     }
 
     #[inline]
-    pub(super) fn backtrack(&mut self, queue_b: usize, bindings_b: usize) {
+    pub(super)
+    fn backtrack(&mut self, queue_b: usize, bindings_b: usize) {
         self.attr_var_queue.truncate(queue_b);
         self.bindings.truncate(bindings_b);
     }
 }
 
 impl MachineState {
-    pub(super) fn push_attr_var_binding(&mut self, h: usize, addr: Addr) {
+    pub(super)
+    fn push_attr_var_binding(&mut self, h: usize, addr: Addr) {
         if self.attr_var_init.bindings.is_empty() {
             self.attr_var_init.instigating_p = self.p.local();
 
@@ -92,7 +96,8 @@ impl MachineState {
         self[temp_v!(2)] = value_list_addr;
     }
 
-    pub(super) fn gather_attr_vars_created_since(&self, b: usize) -> IntoIter<Addr> {
+    pub(super)
+    fn gather_attr_vars_created_since(&self, b: usize) -> IntoIter<Addr> {
         let mut attr_vars: Vec<_> = self.attr_var_init.attr_var_queue[b..]
             .iter()
             .filter_map(|h| match self.store(self.deref(Addr::HeapCell(*h))) {
@@ -109,7 +114,8 @@ impl MachineState {
         attr_vars.into_iter()
     }
 
-    pub(super) fn verify_attr_interrupt(&mut self, p: usize) {
+    pub(super)
+    fn verify_attr_interrupt(&mut self, p: usize) {
         self.allocate(self.num_of_args + 2);
 
         let e = self.e;
index 724b6c54a2e338dbaf099683c4602e6878725491..10b67d4e47f2995d4a88e25986077b95e9971102 100644 (file)
@@ -33,13 +33,13 @@ struct CopyTermState<T: CopierTarget> {
     scan: usize,
     old_h: usize,
     target: T,
-    attr_var_policy: AttrVarPolicy
+    attr_var_policy: AttrVarPolicy,
 }
 
 impl<T: CopierTarget> CopyTermState<T> {
     fn new(target: T, attr_var_policy: AttrVarPolicy) -> Self {
         CopyTermState {
-            trail: vec![],
+            trail: Trail::new(),
             scan: 0,
             old_h: target.threshold(),
             target,
@@ -53,124 +53,86 @@ impl<T: CopierTarget> CopyTermState<T> {
         &mut self.target[scan]
     }
 
-    fn copied_list(&mut self, addr: usize) -> bool {
-        match &self.target[addr] {
-            HeapCellValue::Addr(Addr::Lis(addr)) | HeapCellValue::Addr(Addr::HeapCell(addr)) => {
-                if *addr >= self.old_h {
-                    *self.value_at_scan() = HeapCellValue::Addr(Addr::Lis(*addr));
-                    self.scan += 1;
-                    return true;
-                }
-            }
-            _ => {}
-        };
-
-        false
-    }
-
     fn copy_list(&mut self, addr: usize) {
-        if self.copied_list(addr) {
-            return;
+        if let Addr::Lis(h) = self.target[addr + 1].as_addr(addr + 1) {
+            if h >= self.old_h {
+                *self.value_at_scan() = HeapCellValue::Addr(Addr::Lis(h));
+                self.scan += 1;
+
+                return;
+            }
         }
 
         let threshold = self.target.threshold();
 
         *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));
-
-        self.target.push(HeapCellValue::Addr(ra));
+        for i in 0 .. 2 {
+            let hcv = self.target[addr + i].context_free_clone();
+            self.target.push(hcv);
+        }
 
-        let hcv = HeapCellValue::Addr(self.target[addr + 1].as_addr(addr + 1));
+        let cdr = self.target.store(self.target.deref(Addr::HeapCell(addr + 1)));
 
-        self.target.push(hcv);
+        if let Addr::Lis(_) = cdr {
+            let tail_addr = self.target[addr + 1].as_addr(addr + 1);
 
-        match rd {
-            Addr::AttrVar(h) | Addr::HeapCell(h)
-                if h >= self.old_h => {
-                    self.target[threshold] = HeapCellValue::Addr(rd)
-                }
-            var @ Addr::AttrVar(_)
-          | var @ Addr::HeapCell(..)
-          | var @ Addr::StackCell(..) => {
-                if ra == rd {
-                    self.reinstantiate_var(var, threshold);
-
-                    if let AttrVarPolicy::StripAttributes = self.attr_var_policy {
-                        self.trail.push((Ref::HeapCell(addr), HeapCellValue::Addr(ra)));
-                        self.target[addr] = HeapCellValue::Addr(Addr::HeapCell(threshold));
-                    }
-                } else {
-                    self.target[threshold] = HeapCellValue::Addr(ra);
-                }
-            }
-            _ => {
-                self.trail.push((
-                    Ref::HeapCell(addr),
-                    HeapCellValue::Addr(self.target[addr].as_addr(addr)),
-                ));
+            self.trail.push((
+                Ref::HeapCell(addr + 1),
+                HeapCellValue::Addr(tail_addr),
+            ));
 
-                self.target[addr] = HeapCellValue::Addr(Addr::Lis(threshold))
-            }
-        };
+            self.target[addr + 1] = HeapCellValue::Addr(Addr::Lis(threshold));
+        }
 
         self.scan += 1;
     }
 
-    fn copied_partial_string(&mut self, addr: usize) -> bool {
-        if let &HeapCellValue::Addr(Addr::PStrLocation(h, n)) = &self.target[addr + 1] {
+    fn copy_partial_string(&mut self, addr: usize, n: usize) {
+        if let &HeapCellValue::Addr(Addr::PStrLocation(h, _)) = &self.target[addr] {
             if h >= self.old_h {
                 *self.value_at_scan() = HeapCellValue::Addr(Addr::PStrLocation(h, n));
                 self.scan += 1;
-                return true;
+
+                return;
             }
         }
 
-        false
-    }
-
-    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.value_at_scan() =
+            HeapCellValue::Addr(Addr::PStrLocation(threshold, 0));
 
-        self.trail.push((
-            Ref::HeapCell(addr + 1),
-            trail_item,
-        ));
+        self.scan += 1;
 
-        let pstr =
+        let (pstr, has_tail) =
             match &self.target[addr] {
-                HeapCellValue::PartialString(ref pstr) => {
-                    pstr.clone_from_offset(n)
+                &HeapCellValue::PartialString(ref pstr, has_tail) => {
+                    (pstr.clone_from_offset(n), has_tail)
                 }
                 _ => {
                     unreachable!()
                 }
             };
 
-        self.target.push(HeapCellValue::PartialString(pstr));
-        self.target.push(HeapCellValue::Addr(tail_addr));
-    }
+        self.target.push(HeapCellValue::PartialString(pstr, has_tail));
 
-    fn copy_partial_string_from(&mut self, addr: usize, n: usize) {
-        if self.copied_partial_string(addr) {
-            return;
-        }
+        let replacement = HeapCellValue::Addr(Addr::PStrLocation(threshold, 0));
 
-        let threshold = self.target.threshold();
-
-        self.target[self.scan] =
-            HeapCellValue::Addr(Addr::PStrLocation(threshold, 0));
+        let trail_item = mem::replace(
+            &mut self.target[addr],
+            replacement,
+        );
 
-        self.scan += 1;
+        self.trail.push((
+            Ref::HeapCell(addr),
+            trail_item,
+        ));
 
-        self.copy_partial_string(addr, n);
+        if has_tail {
+            let tail_addr = self.target[addr + 1].as_addr(addr + 1);
+            self.target.push(HeapCellValue::Addr(tail_addr));
+        }
     }
 
     fn reinstantiate_var(&mut self, addr: Addr, frontier: usize) {
@@ -178,6 +140,7 @@ impl<T: CopierTarget> CopyTermState<T> {
             Addr::HeapCell(h) => {
                 self.target[frontier] = HeapCellValue::Addr(Addr::HeapCell(frontier));
                 self.target[h] = HeapCellValue::Addr(Addr::HeapCell(frontier));
+
                 self.trail.push((
                     Ref::HeapCell(h),
                     HeapCellValue::Addr(Addr::HeapCell(h)),
@@ -186,6 +149,7 @@ impl<T: CopierTarget> CopyTermState<T> {
             Addr::StackCell(fr, sc) => {
                 self.target[frontier] = HeapCellValue::Addr(Addr::HeapCell(frontier));
                 self.target.stack().index_and_frame_mut(fr)[sc] = Addr::HeapCell(frontier);
+
                 self.trail.push((
                     Ref::StackCell(fr, sc),
                     HeapCellValue::Addr(Addr::StackCell(fr, sc)),
@@ -199,7 +163,8 @@ impl<T: CopierTarget> CopyTermState<T> {
                 };
 
                 self.target[frontier] = HeapCellValue::Addr(Addr::HeapCell(threshold));
-                self.target[h] = HeapCellValue::Addr(Addr::HeapCell(threshold));
+                self.target[h] = HeapCellValue::Addr(Addr::HeapCell(frontier));
+
                 self.trail.push((
                     Ref::AttrVar(h),
                     HeapCellValue::Addr(Addr::AttrVar(h)),
@@ -212,7 +177,9 @@ impl<T: CopierTarget> CopyTermState<T> {
                     self.target.push(list_val);
                 }
             }
-            _ => unreachable!()
+            _ => {
+                unreachable!()
+            }
         }
     }
 
@@ -234,17 +201,39 @@ impl<T: CopierTarget> CopyTermState<T> {
         }
     }
 
+    fn copy_stream(&mut self, addr: usize) {
+        let threshold = self.target.threshold();
+
+        let trail_item = mem::replace(
+            &mut self.target[addr],
+            HeapCellValue::Addr(Addr::Stream(threshold)),
+        );
+
+        self.trail.push((
+            Ref::HeapCell(addr),
+            trail_item,
+        ));
+
+        self.target.push(HeapCellValue::Stream(Stream::null_stream()));
+
+        self.scan += 1;
+    }
+
     fn copy_structure(&mut self, addr: usize) {
         match self.target[addr].context_free_clone() {
             HeapCellValue::NamedStr(arity, name, fixity) => {
                 let threshold = self.target.threshold();
 
                 *self.value_at_scan() = HeapCellValue::Addr(Addr::Str(threshold));
-                self.target[addr] = HeapCellValue::Addr(Addr::Str(threshold));
+
+                let trail_item = mem::replace(
+                    &mut self.target[addr],
+                    HeapCellValue::Addr(Addr::Str(threshold)),
+                );
 
                 self.trail.push((
                     Ref::HeapCell(addr),
-                    HeapCellValue::NamedStr(arity, name.clone(), fixity.clone()),
+                    trail_item,
                 ));
 
                 self.target.push(HeapCellValue::NamedStr(arity, name, fixity));
@@ -257,7 +246,9 @@ impl<T: CopierTarget> CopyTermState<T> {
             HeapCellValue::Addr(Addr::Str(addr)) => {
                 *self.value_at_scan() = HeapCellValue::Addr(Addr::Str(addr))
             }
-            _ => {}
+            _ => {
+                unreachable!()
+            }
         }
 
         self.scan += 1;
@@ -272,26 +263,30 @@ impl<T: CopierTarget> CopyTermState<T> {
                 &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;
+                            let addr = self.target[h].as_addr(h);
+
+                            if addr == Addr::Con(h) {
+                                *self.value_at_scan() = self.target[h].context_free_clone();
+                            } else {
+                                *self.value_at_scan() = HeapCellValue::Addr(addr);
+                            }
                         }
                         Addr::Lis(h) => {
                             self.copy_list(h);
                         }
-                        addr @ Addr::AttrVar(_)
-                      | addr @ Addr::HeapCell(_)
-                      | addr @ Addr::StackCell(..) => {
+                        addr @ Addr::AttrVar(_) |
+                        addr @ Addr::HeapCell(_) |
+                        addr @ Addr::StackCell(..) => {
                             self.copy_var(addr);
                         }
                         Addr::Str(addr) => {
                             self.copy_structure(addr);
                         }
                         Addr::PStrLocation(addr, n) => {
-                            self.copy_partial_string_from(addr, n);
+                            self.copy_partial_string(addr, n);
+                        }
+                        Addr::Stream(h) => {
+                            self.copy_stream(h);
                         }
                         _ => {
                             self.scan += 1;
index e82aaa048099396ebf69dbfe3e67940135da9f24..a48627719e5d0c4209bd0c7e8d6956b4dcca2528 100644 (file)
@@ -51,13 +51,19 @@ impl Machine {
         };
 
         let arity = match self.machine_st.store(self.machine_st.deref(arity)) {
-            Addr::Con(h) =>
+            Addr::Con(h) => {
                 if let HeapCellValue::Integer(ref arity) = &self.machine_st.heap[h] {
                     arity.to_usize().unwrap()
                 } else {
                     unreachable!()
-                },
-            _ => unreachable!(),
+                }
+            }
+            Addr::Usize(n) => {
+                n
+            }
+            _ => {
+                unreachable!()
+            }
         };
 
         (name, arity)
index d8d39036c7f2f88c5bda84513ef0cad3260c48d0..f979d38a5ab3bbff98efff433464a6cd49181ef4 100644 (file)
@@ -39,12 +39,12 @@ impl<T: RawBlockTraits> Drop for HeapTemplate<T> {
 }
 
 pub(crate)
-struct HeapIntoIterator<T: RawBlockTraits> {
+struct HeapIntoIter<T: RawBlockTraits> {
     offset: usize,
     buf: RawBlock<T>,
 }
 
-impl<T: RawBlockTraits> Drop for HeapIntoIterator<T> {
+impl<T: RawBlockTraits> Drop for HeapIntoIter<T> {
     fn drop(&mut self) {
         let mut heap =
             HeapTemplate { buf: self.buf.take(), _marker: PhantomData };
@@ -54,7 +54,7 @@ impl<T: RawBlockTraits> Drop for HeapIntoIterator<T> {
     }
 }
 
-impl<T: RawBlockTraits> Iterator for HeapIntoIterator<T> {
+impl<T: RawBlockTraits> Iterator for HeapIntoIter<T> {
     type Item = HeapCellValue;
 
     fn next(&mut self) -> Option<Self::Item> {
@@ -72,19 +72,19 @@ impl<T: RawBlockTraits> Iterator for HeapIntoIterator<T> {
 }
 
 pub(crate)
-struct HeapIterator<'a, T: RawBlockTraits> {
+struct HeapIter<'a, T: RawBlockTraits> {
     offset: usize,
     buf: &'a RawBlock<T>,
 }
 
-impl<'a, T: RawBlockTraits> HeapIterator<'a, T> {
+impl<'a, T: RawBlockTraits> HeapIter<'a, T> {
     pub(crate)
     fn new(buf: &'a RawBlock<T>, offset: usize) -> Self {
-        HeapIterator { buf, offset }
+        HeapIter { buf, offset }
     }
 }
 
-impl<'a, T: RawBlockTraits> Iterator for HeapIterator<'a, T> {
+impl<'a, T: RawBlockTraits> Iterator for HeapIter<'a, T> {
     type Item = &'a HeapCellValue;
 
     fn next(&mut self) -> Option<Self::Item> {
@@ -101,20 +101,28 @@ impl<'a, T: RawBlockTraits> Iterator for HeapIterator<'a, T> {
     }
 }
 
+#[allow(dead_code)]
 pub(crate)
-struct HeapIteratorMut<'a, T: RawBlockTraits> {
+fn print_heap_terms<'a, I: Iterator<Item = &'a HeapCellValue>>(heap: I, h: usize) {
+    for (index, term) in heap.enumerate() {
+        println!("{} : {}", h + index, term);
+    }
+}
+
+pub(crate)
+struct HeapIterMut<'a, T: RawBlockTraits> {
     offset: usize,
     buf: &'a mut RawBlock<T>,
 }
 
-impl<'a, T: RawBlockTraits> HeapIteratorMut<'a, T> {
+impl<'a, T: RawBlockTraits> HeapIterMut<'a, T> {
     pub(crate)
     fn new(buf: &'a mut RawBlock<T>, offset: usize) -> Self {
-        HeapIteratorMut { buf, offset }
+        HeapIterMut { buf, offset }
     }
 }
 
-impl<'a, T: RawBlockTraits> Iterator for HeapIteratorMut<'a, T> {
+impl<'a, T: RawBlockTraits> Iterator for HeapIterMut<'a, T> {
     type Item = &'a mut HeapCellValue;
 
     fn next(&mut self) -> Option<Self::Item> {
@@ -160,7 +168,7 @@ impl<T: RawBlockTraits> HeapTemplate<T> {
             &HeapCellValue::Rational(ref r) => {
                 HeapCellValue::Rational(r.clone())
             }
-            &HeapCellValue::PartialString(_) => {
+            &HeapCellValue::PartialString(..) => {
                 HeapCellValue::Addr(Addr::PStrLocation(h, 0))
             }
             &HeapCellValue::Stream(_) => {
@@ -169,6 +177,15 @@ impl<T: RawBlockTraits> HeapTemplate<T> {
         }
     }
 
+    #[inline]
+    fn pop(&mut self) {
+        let h = self.h();
+
+        if h > 0 {
+            self.truncate(h - 1);
+        }
+    }
+
     #[inline]
     pub(crate)
     fn put_constant(&mut self, c: Constant) -> Addr {
@@ -177,40 +194,45 @@ impl<T: RawBlockTraits> HeapTemplate<T> {
                 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)))                
+                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
+                if s.is_empty() {
+                    Addr::EmptyList
+                } else {
+                    let addr = self.allocate_pstr(&s);
+                    self.pop();
+
+                    let h = self.h();
+
+                    match &mut self[h - 1] {
+                        &mut HeapCellValue::PartialString(_, ref mut has_tail) => {
+                            *has_tail = false;
+                        }
+                        _ => {
+                            unreachable!()
+                        }
+                    }
+
+                    addr
+                }
             }
             Constant::Usize(n) => {
-                self.push(HeapCellValue::Addr(Addr::Usize(n)));
                 Addr::Usize(n)
             }
         }
@@ -239,7 +261,7 @@ impl<T: RawBlockTraits> HeapTemplate<T> {
             false
         }
     }
-    
+
     #[inline]
     pub(crate)
     fn integer_at(&self, h: usize) -> bool {
@@ -279,9 +301,12 @@ impl<T: RawBlockTraits> HeapTemplate<T> {
             val @ HeapCellValue::Stream(..) => {
                 Addr::Stream(self.push(val))
             }
-            val @ HeapCellValue::PartialString(_) => {
-                let h = self.push(val);
-                self.push(HeapCellValue::Addr(Addr::EmptyList));
+            HeapCellValue::PartialString(pstr, has_tail) => {
+                let h = self.push(HeapCellValue::PartialString(pstr, has_tail));
+
+                if has_tail {
+                    self.push(HeapCellValue::Addr(Addr::EmptyList));
+                }
 
                 Addr::Con(h)
             }
@@ -296,7 +321,8 @@ impl<T: RawBlockTraits> HeapTemplate<T> {
                 let h = self.h();
 
                 self.push(HeapCellValue::PartialString(
-                    PartialString::empty()
+                    PartialString::empty(),
+                    true,
                 ));
 
                 self.push(HeapCellValue::Addr(
@@ -343,7 +369,7 @@ impl<T: RawBlockTraits> HeapTemplate<T> {
                     }
                 };
 
-            self.push(HeapCellValue::PartialString(pstr));
+            self.push(HeapCellValue::PartialString(pstr, true));
 
             if rest_src != "" {
                 self.push(HeapCellValue::Addr(Addr::PStrLocation(h + 2, 0)));
@@ -414,7 +440,7 @@ impl<T: RawBlockTraits> HeapTemplate<T> {
             self.push(HeapCellValue::Addr(Addr::Lis(h + 1)));
             self.push(value);
 
-            h += mem::size_of::<HeapCellValue>() * 2;
+            h += 2;
         }
 
         self.push(HeapCellValue::Addr(Addr::EmptyList));
@@ -424,18 +450,18 @@ impl<T: RawBlockTraits> HeapTemplate<T> {
 
     /* Create an iterator starting from the passed offset. */
     pub(crate)
-    fn iter_from<'a>(&'a self, offset: usize) -> HeapIterator<'a, T> {
-        HeapIterator::new(&self.buf, offset * mem::size_of::<HeapCellValue>())
+    fn iter_from<'a>(&'a self, offset: usize) -> HeapIter<'a, T> {
+        HeapIter::new(&self.buf, offset * mem::size_of::<HeapCellValue>())
     }
 
     pub(crate)
-    fn iter_mut_from<'a>(&'a mut self, offset: usize) -> HeapIteratorMut<'a, T> {
-        HeapIteratorMut::new(&mut self.buf, offset * mem::size_of::<HeapCellValue>())
+    fn iter_mut_from<'a>(&'a mut self, offset: usize) -> HeapIterMut<'a, T> {
+        HeapIterMut::new(&mut self.buf, offset * mem::size_of::<HeapCellValue>())
     }
 
     pub(crate)
-    fn into_iter(mut self) -> HeapIntoIterator<T> {
-        HeapIntoIterator { buf: self.buf.take(), offset: 0 }
+    fn into_iter(mut self) -> HeapIntoIter<T> {
+        HeapIntoIter { buf: self.buf.take(), offset: 0 }
     }
 
     pub(crate)
index 0a352a660ee64ef02b3bd58894deed8986b41c7d..1f3dc1803a42abeaedc19d58d76a03682655b588 100644 (file)
@@ -222,7 +222,7 @@ impl MachineError {
                     SharedOpDesc::new(400, YFX),
                     [clause_name(name), integer(arity)]
                 );
-                
+
                 let stub = functor!(
                     "existence_error",
                     [atom("procedure"), aux(h, 0)],
@@ -286,7 +286,7 @@ impl MachineError {
     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");
@@ -352,7 +352,7 @@ impl MachineError {
 
         let location = err.line_and_col_num();
         let stub = functor!(err.as_str());
-        
+
         let stub = functor!(
             "syntax_error",
             [aux(h, 0)],
@@ -608,7 +608,7 @@ impl MachineState {
     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 sorted = self.store(self.deref(self[temp_v!(2)].clone()));
 
index b2dff1592bd3f460e3cbf831e22fc1144436bb98..c5fc505a347964aeb8050f24d72beaade0d4b573 100644 (file)
@@ -152,6 +152,20 @@ impl PartialOrd<Ref> for Addr {
 }
 
 impl Addr {
+    #[inline]
+    pub fn is_heap_bound(&self) -> bool {
+        match self {
+            Addr::Char(_) | Addr::CharCode(_) | Addr::EmptyList
+          | Addr::CutPoint(_) | Addr::Usize(_) | Addr::Float(_) => {
+                false
+            }
+            _ => {
+                true
+            }
+        }
+    }
+
+    #[inline]
     pub fn is_ref(&self) -> bool {
         match self {
             Addr::HeapCell(_) | Addr::StackCell(_, _) | Addr::AttrVar(_) => {
@@ -163,6 +177,7 @@ impl Addr {
         }
     }
 
+    #[inline]
     pub fn as_var(&self) -> Option<Ref> {
         match self {
             &Addr::AttrVar(h) => Some(Ref::AttrVar(h)),
@@ -173,7 +188,7 @@ impl Addr {
     }
 
     pub(super)
-    fn order_category(&self, heap: &Heap) -> Option<TermOrderCategory> {                
+    fn order_category(&self, heap: &Heap) -> Option<TermOrderCategory> {
         match self {
             Addr::HeapCell(_) | Addr::AttrVar(_) | Addr::StackCell(..) => {
                 Some(TermOrderCategory::Variable)
@@ -200,18 +215,21 @@ impl Addr {
                     }
                 }
             }
-            Addr::Char(_) | Addr::CharCode(_) | Addr::EmptyList => {
+            Addr::Char(_) | Addr::EmptyList => {
                 Some(TermOrderCategory::Atom)
             }
+            Addr::Usize(_) | Addr::CharCode(_) => {
+                Some(TermOrderCategory::Integer)
+            }
             Addr::Lis(_) | Addr::PStrLocation(..) | Addr::Str(_) => {
                 Some(TermOrderCategory::Compound)
             }
-            Addr::CutPoint(_) | Addr::Usize(_) | Addr::Stream(_) => {
+            Addr::CutPoint(_) | Addr::Stream(_) => {
                 None
             }
         }
     }
-    
+
     pub fn as_constant(&self, machine_st: &MachineState) -> Option<Constant> {
         match self {
             &Addr::Char(c) => {
@@ -236,12 +254,30 @@ impl Addr {
                     }
                 }
             }
+            &Addr::EmptyList => {
+                Some(Constant::EmptyList)
+            }
             &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)))
+                let mut heap_pstr_iter =
+                    machine_st.heap_pstr_iter(Addr::PStrLocation(h, n));
+                
+                let mut buf = String::new();
+
+                while let Some(Some(c)) = heap_pstr_iter.next() {
+                    buf.push(c);
+                }
+
+                let end_addr =
+                    machine_st.store(machine_st.deref(heap_pstr_iter.focus()));
+
+                if let Addr::EmptyList = end_addr {
+                    Some(Constant::String(Rc::new(buf)))
+                } else {
+                    None
+                }
             }
             _ => {
                 None
@@ -262,6 +298,8 @@ impl Add<usize> for Addr {
 
     fn add(self, rhs: usize) -> Self::Output {
         match self {
+            Addr::Stream(h) => Addr::Stream(h + rhs),
+            Addr::Con(h) => Addr::Con(h + rhs),
             Addr::Lis(a) => Addr::Lis(a + rhs),
             Addr::AttrVar(h) => Addr::AttrVar(h + rhs),
             Addr::HeapCell(h) => Addr::HeapCell(h + rhs),
@@ -278,6 +316,8 @@ impl Sub<i64> for Addr {
     fn sub(self, rhs: i64) -> Self::Output {
         if rhs < 0 {
             match self {
+                Addr::Stream(h) => Addr::Stream(h + rhs.abs() as usize),
+                Addr::Con(h) => Addr::Con(h + rhs.abs() as usize),
                 Addr::Lis(a) => Addr::Lis(a + rhs.abs() as usize),
                 Addr::AttrVar(h) => Addr::AttrVar(h + rhs.abs() as usize),
                 Addr::HeapCell(h) => Addr::HeapCell(h + rhs.abs() as usize),
@@ -296,6 +336,8 @@ impl Sub<usize> for Addr {
 
     fn sub(self, rhs: usize) -> Self::Output {
         match self {
+            Addr::Stream(h) => Addr::Stream(h - rhs),
+            Addr::Con(h) => Addr::Con(h - rhs),
             Addr::Lis(a) => Addr::Lis(a - rhs),
             Addr::AttrVar(h) => Addr::AttrVar(h - rhs),
             Addr::HeapCell(h) => Addr::HeapCell(h - rhs),
@@ -331,8 +373,8 @@ pub enum HeapCellValue {
     DBRef(DBRef),
     Integer(Rc<Integer>),
     NamedStr(usize, ClauseName, Option<SharedOpDesc>), // arity, name, precedence/Specifier if it has one.
-    Rational(Rc<Rational>),    
-    PartialString(PartialString),
+    Rational(Rc<Rational>),
+    PartialString(PartialString, bool), // the partial string, a bool indicating whether it came from a Constant.
     Stream(Stream),
 }
 
@@ -341,7 +383,7 @@ impl HeapCellValue {
     pub fn as_addr(&self, focus: usize) -> Addr {
         match self {
             HeapCellValue::Addr(ref a) => {
-                a.clone()
+                *a
             }
             HeapCellValue::Atom(..) | HeapCellValue::DBRef(..) | HeapCellValue::Integer(..) |
             HeapCellValue::Rational(..) => {
@@ -350,7 +392,7 @@ impl HeapCellValue {
             HeapCellValue::NamedStr(_, _, _) => {
                 Addr::Str(focus)
             }
-            HeapCellValue::PartialString(_) => {
+            HeapCellValue::PartialString(..) => {
                 Addr::PStrLocation(focus, 0)
             }
             HeapCellValue::Stream(_) => {
@@ -380,8 +422,8 @@ impl HeapCellValue {
             &HeapCellValue::Rational(ref r) => {
                 HeapCellValue::Rational(r.clone())
             }
-            &HeapCellValue::PartialString(ref pstr) => {
-                HeapCellValue::PartialString(pstr.clone())
+            &HeapCellValue::PartialString(ref pstr, has_tail) => {
+                HeapCellValue::PartialString(pstr.clone(), has_tail)
             }
             &HeapCellValue::Stream(_) => {
                 HeapCellValue::Stream(Stream::null_stream())
index 88862e0fee10432083cfc3024a88a6a215f76e69..f5077d9dbfd8bd1c3370803dd3ef8223942ce056 100644 (file)
@@ -14,11 +14,105 @@ use crate::prolog::rug::Integer;
 
 use downcast::Any;
 
+use indexmap::IndexSet;
+
 use std::cmp::Ordering;
 use std::io::Write;
 use std::mem;
 use std::ops::{Index, IndexMut};
 
+pub(crate)
+struct HeapPStrIter<'a> {
+    focus: Addr,
+    machine_st: &'a MachineState,
+    seen: IndexSet<Addr>,
+}
+
+impl<'a> HeapPStrIter<'a> {
+    #[inline]
+    fn new(machine_st: &'a MachineState, focus: Addr) -> Self {
+        HeapPStrIter {
+            focus,
+            machine_st,
+            seen: IndexSet::new(),
+        }
+    }
+
+    #[inline]
+    pub(crate)
+    fn focus(&'a self) -> Addr {
+        self.focus
+    }
+}
+
+impl<'a> Iterator for HeapPStrIter<'a> {
+    type Item = Option<char>;
+
+    fn next(&mut self) -> Option<Self::Item> {
+        let addr = self.machine_st.store(self.machine_st.deref(self.focus));
+
+        if !self.seen.contains(&addr) {
+            self.seen.insert(addr);
+        } else {
+            return None;
+        }
+        
+        match addr {
+            Addr::PStrLocation(h, n) => {
+                if let &HeapCellValue::PartialString(ref pstr, _) = &self.machine_st.heap[h] {
+                    if let Some(c) = pstr.range_from(n ..).next() {
+                        self.focus = Addr::PStrLocation(h, n + c.len_utf8());
+                        return Some(Some(c));
+                    } else {
+                        unreachable!()
+                    }
+                } else {
+                    unreachable!()
+                }
+            }
+            Addr::Lis(l) => {
+                let addr = self.machine_st.store(self.machine_st.deref(Addr::HeapCell(l)));
+                
+                if let Addr::Char(c) = addr {
+                    self.focus = Addr::HeapCell(l + 1);
+                    return Some(Some(c));
+                } else {
+                    return None;
+                }
+            }
+            Addr::EmptyList => {
+                self.focus = Addr::EmptyList;
+                return Some(None);
+            }
+            _ => {
+                return None;
+            }
+        }
+    }
+}
+
+#[inline]
+pub(super)
+fn compare_pstr<'a>(
+    pstr_iter: HeapPStrIter<'a>,
+    mut c_iter: impl Iterator<Item = char>,
+) -> bool {    
+    for opt_c in pstr_iter {
+        match opt_c {
+            Some(_) => {
+                if opt_c != c_iter.next() {
+                    return false;
+                }
+            }
+            None => {
+                return c_iter.next().is_none();
+            }
+        }
+    }
+
+    false
+}
+
 pub struct Ball {
     pub(super) boundary: usize,
     pub(super) stub: Heap,
@@ -185,7 +279,7 @@ impl<'a> CopierTarget for CopyBallTerm<'a> {
                 self.stub[index].as_addr(h)
             }
             Addr::StackCell(fr, sc) => {
-                self.stack.index_and_frame(fr)[sc].clone()
+                self.stack.index_and_frame(fr)[sc]
             }
             addr => {
                 addr
@@ -195,7 +289,7 @@ impl<'a> CopierTarget for CopyBallTerm<'a> {
 
     fn deref(&self, mut addr: Addr) -> Addr {
         loop {
-            let value = self.store(addr.clone());
+            let value = self.store(addr);
 
             if value.is_ref() && value != addr {
                 addr = value;
@@ -264,11 +358,13 @@ impl HeapPtr {
                 Addr::HeapCell(h)
             }
             &HeapPtr::PStrChar(h, n) => {
-                if let HeapCellValue::PartialString(ref pstr) = &heap[h] {
+                if let &HeapCellValue::PartialString(ref pstr, has_tail) = &heap[h] {
                     if let Some(c) = pstr.range_from(n ..).next() {
                         Addr::Char(c)
-                    } else {
+                    } else if has_tail {
                         Addr::HeapCell(h + 1)
+                    } else {
+                        Addr::EmptyList
                     }
                 } else {
                     unreachable!()
@@ -315,13 +411,19 @@ pub struct MachineState {
 }
 
 impl MachineState {
+    #[inline]
+    pub(crate)
+    fn heap_pstr_iter<'a>(&'a self, focus: Addr) -> HeapPStrIter<'a> {
+        HeapPStrIter::new(self, focus)
+    }
+
     pub(super)
     fn try_char_list(&self, addrs: Vec<Addr>) -> Result<String, MachineError> {
         let mut chars = String::new();
         let mut iter = addrs.iter();
 
         while let Some(addr) = iter.next() {
-            let addr = self.store(self.deref(addr.clone()));
+            let addr = self.store(self.deref(*addr));
 
             match addr {
                 Addr::Char(c) => {
@@ -480,7 +582,7 @@ pub(crate) trait CallPolicy: Any {
         let n = machine_st.stack.index_or_frame(b).prelude.univ_prelude.num_cells;
 
         for i in 1 .. n + 1 {
-            machine_st.registers[i] = machine_st.stack.index_or_frame(b)[i-1].clone();
+            machine_st.registers[i] = machine_st.stack.index_or_frame(b)[i-1];
         }
 
         machine_st.num_of_args = n;
@@ -519,7 +621,7 @@ pub(crate) trait CallPolicy: Any {
         let n = machine_st.stack.index_or_frame(b).prelude.univ_prelude.num_cells;
 
         for i in 1 .. n + 1 {
-            machine_st.registers[i] = machine_st.stack.index_or_frame(b)[i-1].clone();
+            machine_st.registers[i] = machine_st.stack.index_or_frame(b)[i-1];
         }
 
         machine_st.num_of_args = n;
@@ -555,7 +657,7 @@ pub(crate) trait CallPolicy: Any {
         let n = machine_st.stack.index_or_frame(b).prelude.univ_prelude.num_cells;
 
         for i in 1 .. n + 1 {
-            machine_st.registers[i] = machine_st.stack.index_or_frame(b)[i-1].clone();
+            machine_st.registers[i] = machine_st.stack.index_or_frame(b)[i-1];
         }
 
         machine_st.num_of_args = n;
@@ -595,7 +697,7 @@ pub(crate) trait CallPolicy: Any {
         let n = machine_st.stack.index_or_frame(b).prelude.univ_prelude.num_cells;
 
         for i in 1 .. n + 1 {
-            machine_st.registers[i] = machine_st.stack.index_or_frame(b)[i-1].clone();
+            machine_st.registers[i] = machine_st.stack.index_or_frame(b)[i-1];
         }
 
         machine_st.num_of_args = n;
@@ -717,7 +819,7 @@ pub(crate) trait CallPolicy: Any {
     ) -> CallResult {
         match ct {
             &BuiltInClauseType::AcyclicTerm => {
-                let addr = machine_st[temp_v!(1)].clone();
+                let addr = machine_st[temp_v!(1)];
                 machine_st.fail = machine_st.is_cyclic_term(addr);
                 return_from_clause!(machine_st.last_call, machine_st)
             }
@@ -726,9 +828,9 @@ pub(crate) trait CallPolicy: Any {
                 return_from_clause!(machine_st.last_call, machine_st)
             }
             &BuiltInClauseType::Compare => {
-                let a1 = machine_st[temp_v!(1)].clone();
-                let a2 = machine_st[temp_v!(2)].clone();
-                let a3 = machine_st[temp_v!(3)].clone();
+                let a1 = machine_st[temp_v!(1)];
+                let a2 = machine_st[temp_v!(2)];
+                let a3 = machine_st[temp_v!(3)];
 
                 let atom = match machine_st.compare_term_test(&a2, &a3) {
                     Some(Ordering::Greater) => {
@@ -769,7 +871,7 @@ pub(crate) trait CallPolicy: Any {
                     &indices.op_dir,
                 ) {
                     Ok(offset) => {
-                        let addr = machine_st[temp_v!(1)].clone();
+                        let addr = machine_st[temp_v!(1)];
                         machine_st.unify(addr, Addr::HeapCell(offset.heap_loc));
                     }
                     Err(e) => {
@@ -789,8 +891,8 @@ pub(crate) trait CallPolicy: Any {
                 return_from_clause!(machine_st.last_call, machine_st)
             }
             &BuiltInClauseType::Eq => {
-                let a1 = machine_st[temp_v!(1)].clone();
-                let a2 = machine_st[temp_v!(2)].clone();
+                let a1 = machine_st[temp_v!(1)];
+                let a2 = machine_st[temp_v!(2)];
 
                 machine_st.fail = machine_st.eq_test(a1, a2);
                 return_from_clause!(machine_st.last_call, machine_st)
@@ -804,8 +906,8 @@ pub(crate) trait CallPolicy: Any {
                 return_from_clause!(machine_st.last_call, machine_st)
             }
             &BuiltInClauseType::NotEq => {
-                let a1 = machine_st[temp_v!(1)].clone();
-                let a2 = machine_st[temp_v!(2)].clone();
+                let a1 = machine_st[temp_v!(1)];
+                let a2 = machine_st[temp_v!(2)];
 
                 machine_st.fail =
                     if let Some(Ordering::Equal) = machine_st.compare_term_test(&a1, &a2) {
@@ -830,7 +932,7 @@ pub(crate) trait CallPolicy: Any {
 
                 let heap_addr = Addr::HeapCell(machine_st.heap.to_list(list.into_iter()));
 
-                let r2 = machine_st[temp_v!(2)].clone();
+                let r2 = machine_st[temp_v!(2)];
                 machine_st.unify(r2, heap_addr);
 
                 return_from_clause!(machine_st.last_call, machine_st)
@@ -854,13 +956,13 @@ pub(crate) trait CallPolicy: Any {
                 let key_pairs = key_pairs.into_iter().map(|kp| kp.1);
                 let heap_addr = Addr::HeapCell(machine_st.heap.to_list(key_pairs));
 
-                let r2 = machine_st[temp_v!(2)].clone();
+                let r2 = machine_st[temp_v!(2)];
                 machine_st.unify(r2, heap_addr);
 
                 return_from_clause!(machine_st.last_call, machine_st)
             }
             &BuiltInClauseType::Is(r, ref at) => {
-                let a1 = machine_st[r].clone();
+                let a1 = machine_st[r];
                 let n2 = machine_st.get_number(at)?;
 
                 let n2 = Addr::Con(machine_st.heap.push(n2.into()));
@@ -1142,13 +1244,13 @@ fn cut_body(machine_st: &mut MachineState, addr: &Addr) -> bool {
 pub(crate) struct DefaultCutPolicy {}
 
 pub(super) fn deref_cut(machine_st: &mut MachineState, r: RegType) {
-    let addr = machine_st.store(machine_st.deref(machine_st[r].clone()));
+    let addr = machine_st.store(machine_st.deref(machine_st[r]));
     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();
+        let addr = machine_st[r];
         cut_body(machine_st, &addr)
     }
 }
@@ -1209,7 +1311,7 @@ impl CutPolicy for SCCCutPolicy {
     fn cut(&mut self, machine_st: &mut MachineState, r: RegType) -> bool {
         let b = machine_st.b;
 
-        match machine_st[r].clone() {
+        match machine_st[r] {
             Addr::Usize(b0) | Addr::CutPoint(b0) => {
                 if b > b0 {
                     machine_st.b = b0;
index fd721fa1c7651002c60c6418f0eb85b2ab0e1afb..b7c56b7873e603cb6ce5b856bd7b72f221507cb3 100644 (file)
@@ -96,13 +96,6 @@ impl MachineState {
         }
     }
 
-    #[allow(dead_code)]
-    pub fn print_heap(&self, start: usize) {
-        for h in start .. self.heap.h() {
-            println!("{} : {}", h, self.heap[h]);
-        }
-    }
-
     #[inline]
     pub fn machine_flags(&self) -> MachineFlags {
         self.flags
@@ -115,14 +108,16 @@ impl MachineState {
                 self.heap[h].as_addr(h)
             }
             Addr::StackCell(fr, sc) => {
-                self.stack.index_and_frame(fr)[sc].clone()
+                self.stack.index_and_frame(fr)[sc]
             }
             Addr::PStrLocation(h, n) => {
-                if let HeapCellValue::PartialString(ref pstr) = &self.heap[h] {
+                if let &HeapCellValue::PartialString(ref pstr, has_tail) = &self.heap[h] {
                     if !pstr.at_end(n) {
                         Addr::PStrLocation(h, n)
-                    } else {
+                    } else if has_tail {
                         Addr::HeapCell(h + 1)
+                    } else {
+                        Addr::EmptyList
                     }
                 } else {
                     unreachable!()
@@ -137,7 +132,7 @@ impl MachineState {
     pub(crate)
     fn deref(&self, mut addr: Addr) -> Addr {
         loop {
-            let value = self.store(addr.clone());
+            let value = self.store(addr);
 
             if value.is_ref() && value != addr {
                 addr = value;
@@ -159,7 +154,7 @@ impl MachineState {
                 self.trail(TrailRef::Ref(Ref::StackCell(fr, sc)));
             }
             _ => {
-                self.push_attr_var_binding(h, addr.clone());
+                self.push_attr_var_binding(h, addr);
                 self.heap[h] = HeapCellValue::Addr(addr);
                 self.trail(TrailRef::Ref(Ref::AttrVar(h)));
             }
@@ -169,7 +164,7 @@ impl MachineState {
     pub(super)
     fn bind(&mut self, r1: Ref, a2: Addr) {
         let t1 = self.store(r1.as_addr());
-        let t2 = self.store(a2.clone());
+        let t2 = self.store(a2);
 
         if t1.is_ref() && (!t2.is_ref() || a2 < r1) {
             match r1 {
@@ -235,13 +230,13 @@ impl MachineState {
                 let d1 = self.store(d1);
                 let d2 = self.store(d2);
 
-                if tabu_list.contains(&(d1.clone(), d2.clone())) {
+                if tabu_list.contains(&(d1, d2)) {
                     continue;
                 } else {
-                    tabu_list.insert((d1.clone(), d2.clone()));
+                    tabu_list.insert((d1, d2));
                 }
 
-                match (d1.clone(), d2.clone()) {
+                match (d1, d2) {
                     (Addr::AttrVar(h), addr) | (addr, Addr::AttrVar(h)) => {
                         self.bind_with_occurs_check(Ref::AttrVar(h), addr)
                     }
@@ -268,7 +263,7 @@ impl MachineState {
                     }
                     (Addr::PStrLocation(h, n), Addr::Lis(l))
                   | (Addr::Lis(l), Addr::PStrLocation(h, n)) => {
-                        if let HeapCellValue::PartialString(ref pstr) = &self.heap[h] {
+                        if let 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));
@@ -283,8 +278,8 @@ impl MachineState {
                         }
                     }
                     (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] {
+                        if let &HeapCellValue::PartialString(ref pstr1, has_tail_1) = &self.heap[h1] {
+                            if let &HeapCellValue::PartialString(ref pstr2, has_tail_2) = &self.heap[h2] {
                                 let pstr1_iter = pstr1.range_from(n1 ..);
                                 let pstr2_iter = pstr2.range_from(n2 ..);
 
@@ -296,19 +291,38 @@ impl MachineState {
                                         return;
                                     }
 
-                                    m_len += 1;
+                                    m_len += c1.len_utf8();
                                 }
 
                                 if pstr1.at_end(n1 + m_len) {
-                                    pdl.push(Addr::HeapCell(h1 + 1));
-                                    pdl.push(Addr::PStrLocation(h2, n2 + m_len));
+                                    if has_tail_1 {
+                                        pdl.push(Addr::HeapCell(h1 + 1));
+                                    } else {
+                                        pdl.push(Addr::EmptyList);
+                                    }
+
+                                    if pstr2.at_end(n2 + m_len) {
+                                        if has_tail_2 {
+                                            pdl.push(Addr::HeapCell(h2 + 1));
+                                        } else {
+                                            pdl.push(Addr::EmptyList);
+                                        }
+                                    } else {
+                                        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;
+                                    if pstr2.at_end(n2 + m_len) {
+                                        if has_tail_2 {
+                                            pdl.push(Addr::HeapCell(h2 + 1));
+                                        } else {
+                                            pdl.push(Addr::EmptyList);
+                                        }
+                                    } else {
+                                        pdl.push(Addr::PStrLocation(h2, n2 + m_len));
+                                    }
+                                }
                             } else {
                                 unreachable!()
                             }
@@ -323,11 +337,6 @@ impl MachineState {
                         pdl.push(Addr::HeapCell(a1 + 1));
                         pdl.push(Addr::HeapCell(a2 + 1));
                     }
-                    (Addr::Con(c1), Addr::Con(c2)) => {
-                        if c1 != c2 {
-                            self.fail = true;
-                        }
-                    }
                     (Addr::Str(a1), Addr::Str(a2)) => {
                         let r1 = &self.heap[a1];
                         let r2 = &self.heap[a2];
@@ -347,7 +356,79 @@ impl MachineState {
 
                         self.fail = true;
                     }
-                    _ => self.fail = true,
+                    (Addr::Con(c1), Addr::Con(c2)) => {
+                        match (&self.heap[c1], &self.heap[c2]) {
+                            (
+                                &HeapCellValue::Atom(ref n1, _),
+                                &HeapCellValue::Atom(ref n2, _),
+                            ) if n1.as_str() == n2.as_str() => {
+                            }
+                            (
+                                &HeapCellValue::DBRef(ref db_ref_1),
+                                &HeapCellValue::DBRef(ref db_ref_2),
+                            ) if db_ref_1 == db_ref_2 => {
+                            }
+                            (
+                                &HeapCellValue::Integer(ref n1),
+                                &HeapCellValue::Integer(ref n2),
+                            ) if &**n1 == &**n2 => {
+                            }
+                            (
+                                &HeapCellValue::Rational(ref n1),
+                                &HeapCellValue::Rational(ref n2),
+                            ) if &**n1 == &**n2 => {
+                            }
+                            _ => {
+                                self.fail = true;
+                            }
+                        }
+                    }
+                    (Addr::Con(h), Addr::Char(c)) | (Addr::Char(c), Addr::Con(h)) => {
+                        match &self.heap[h] {
+                            &HeapCellValue::Atom(ref name, _) if name.is_char() => {
+                                if name.as_str().chars().next() != Some(c) {
+                                    self.fail = true;
+                                    return;
+                                }
+                            }
+                            _ => {
+                                self.fail = true;
+                                return;
+                            }
+                        }
+                    }
+                    (Addr::Usize(n1), Addr::Con(n2)) | (Addr::Con(n2), Addr::Usize(n1)) => {
+                        if let HeapCellValue::Integer(ref n2) = &self.heap[n2] {
+                            if let Some(n2) = n2.to_usize() {
+                                if n1 == n2 {
+                                    continue;
+                                }
+                            }
+                        }
+
+                        self.fail = true;
+                    }
+                    (Addr::CharCode(n1), Addr::Con(n2)) | (Addr::Con(n2), Addr::CharCode(n1)) => {
+                        if let HeapCellValue::Integer(ref n2) = &self.heap[n2] {
+                            if let Some(n2) = n2.to_u32() {
+                                if n1 == n2 {
+                                    continue;
+                                }
+                            }
+                        }
+
+                        self.fail = true;
+                    }
+                    (Addr::Stream(s1), Addr::Stream(s2)) => {
+                        if s1 != s2 {
+                            self.fail = true;
+                        }
+                    }
+                    (a1, a2) => {
+                        if a1 != a2 {
+                            self.fail = true;
+                        }
+                    }
                 };
             }
         }
@@ -369,13 +450,13 @@ impl MachineState {
                 let d1 = self.store(d1);
                 let d2 = self.store(d2);
 
-                if tabu_list.contains(&(d1.clone(), d2.clone())) {
+                if tabu_list.contains(&(d1, d2)) {
                     continue;
                 } else {
-                    tabu_list.insert((d1.clone(), d2.clone()));
+                    tabu_list.insert((d1, d2));
                 }
 
-                match (d1.clone(), d2.clone()) {
+                match (d1, d2) {
                     (Addr::AttrVar(h), addr) | (addr, Addr::AttrVar(h)) => {
                         self.bind(Ref::AttrVar(h), addr);
                     }
@@ -402,7 +483,7 @@ impl MachineState {
                     }
                     (Addr::PStrLocation(h, n), Addr::Lis(l))
                   | (Addr::Lis(l), Addr::PStrLocation(h, n)) => {
-                      if let HeapCellValue::PartialString(ref pstr) = &self.heap[h] {
+                      if let 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));
@@ -417,8 +498,8 @@ impl MachineState {
                       }
                     }
                     (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] {
+                        if let &HeapCellValue::PartialString(ref pstr1, has_tail_1) = &self.heap[h1] {
+                            if let &HeapCellValue::PartialString(ref pstr2, has_tail_2) = &self.heap[h2] {
                                 let pstr1_iter = pstr1.range_from(n1 ..);
                                 let pstr2_iter = pstr2.range_from(n2 ..);
 
@@ -430,19 +511,38 @@ impl MachineState {
                                         return;
                                     }
 
-                                    m_len += 1;
+                                    m_len += c1.len_utf8();
                                 }
 
                                 if pstr1.at_end(n1 + m_len) {
-                                    pdl.push(Addr::HeapCell(h1 + 1));
-                                    pdl.push(Addr::PStrLocation(h2, n2 + m_len));
+                                    if has_tail_1 {
+                                        pdl.push(Addr::HeapCell(h1 + 1));
+                                    } else {
+                                        pdl.push(Addr::EmptyList);
+                                    }
+
+                                    if pstr2.at_end(n2 + m_len) {
+                                        if has_tail_2 {
+                                            pdl.push(Addr::HeapCell(h2 + 1));
+                                        } else {
+                                            pdl.push(Addr::EmptyList);
+                                        }
+                                    } else {
+                                        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;
+                                    if pstr2.at_end(n2 + m_len) {
+                                        if has_tail_2 {
+                                            pdl.push(Addr::HeapCell(h2 + 1));
+                                        } else {
+                                            pdl.push(Addr::EmptyList);
+                                        }
+                                    } else {
+                                        pdl.push(Addr::PStrLocation(h2, n2 + m_len));
+                                    }
+                                }
                             }
                         }
                     }
@@ -453,11 +553,6 @@ impl MachineState {
                         pdl.push(Addr::HeapCell(a1 + 1));
                         pdl.push(Addr::HeapCell(a2 + 1));
                     }
-                    (Addr::Con(c1), Addr::Con(c2)) => {
-                        if c1 != c2 {
-                            self.fail = true;
-                        }
-                    }
                     (Addr::Str(a1), Addr::Str(a2)) => {
                         let r1 = &self.heap[a1];
                         let r2 = &self.heap[a2];
@@ -477,49 +572,82 @@ impl MachineState {
 
                         self.fail = true;
                     }
-                    _ => 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;
-        }
+                    (Addr::Con(c1), Addr::Con(c2)) => {
+                        match (&self.heap[c1], &self.heap[c2]) {
+                            (
+                                &HeapCellValue::Atom(ref n1, _),
+                                &HeapCellValue::Atom(ref n2, _),
+                            ) if n1.as_str() == n2.as_str() => {
+                            }
+(
+                                &HeapCellValue::DBRef(ref db_ref_1),
+                                &HeapCellValue::DBRef(ref db_ref_2),
+                            ) if db_ref_1 == db_ref_2 => {
+                            }
+                            (
+                                &HeapCellValue::Integer(ref n1),
+                                &HeapCellValue::Integer(ref n2),
+                            ) if &**n1 == &**n2 => {
+                            }
+                            (
+                                &HeapCellValue::Rational(ref n1),
+                                &HeapCellValue::Rational(ref n2),
+                            ) if &**n1 == &**n2 => {
+                            }
+                            _ => {
+                                self.fail = true;
+                            }
+                        }
+                    }
+                    (Addr::Con(h), Addr::Char(c)) | (Addr::Char(c), Addr::Con(h)) => {
+                        match &self.heap[h] {
+                            &HeapCellValue::Atom(ref name, _) if name.is_char() => {
+                                if name.as_str().chars().next() != Some(c) {
+                                    self.fail = true;
+                                    return;
+                                }
+                            }
+                            _ => {
+                                self.fail = true;
+                                return;
+                            }
+                        }
+                    }
+                    (Addr::Usize(n1), Addr::Con(n2)) | (Addr::Con(n2), Addr::Usize(n1)) => {
+                        if let HeapCellValue::Integer(ref n2) = &self.heap[n2] {
+                            if let Some(n2) = n2.to_usize() {
+                                if n1 == n2 {
+                                    continue;
+                                }
+                            }
+                        }
 
-        let mut addr = Addr::PStrLocation(h, n);
-        let mut result = String::new();
+                        self.fail = true;
+                    }
+                    (Addr::CharCode(n1), Addr::Con(n2)) | (Addr::Con(n2), Addr::CharCode(n1)) => {
+                        if let HeapCellValue::Integer(ref n2) = &self.heap[n2] {
+                            if let Some(n2) = n2.to_u32() {
+                                if n1 == n2 {
+                                    continue;
+                                }
+                            }
+                        }
 
-        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;
+                        self.fail = true;
                     }
-                }
-                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!()
+                    (Addr::Stream(s1), Addr::Stream(s2)) => {
+                        if s1 != s2 {
+                            self.fail = true;
+                        }
                     }
-                }
-                _ => {
-                    return None;
-                }
+                    (a1, a2) => {
+                        if a1 != a2 {
+                            self.fail = true;
+                        }
+                    }
+                };
             }
         }
-
-        Some(result)
     }
 
     pub(super)
@@ -566,7 +694,7 @@ impl MachineState {
             &mut HeapPtr::PStrChar(h, ref mut n)
           | &mut HeapPtr::PStrLocation(h, ref mut n) => {
                 match &self.heap[h] {
-                    HeapCellValue::PartialString(ref pstr) => {
+                    HeapCellValue::PartialString(ref pstr, _) => {
                         for c in pstr.range_from(*n ..).take(rhs) {
                             *n += c.len_utf8();
                         }
@@ -648,18 +776,30 @@ impl MachineState {
         match self.store(self.deref(addr)) {
             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::Atom(ref n1, _) => {
+                        match c {
+                            Constant::Atom(ref n2, _) => {
+                                n1 != n2
+                            }
+                            Constant::Char(c) if n1.is_char() => {
+                                Some(*c) != n1.as_str().chars().next()
+                            }
+                            _ => {
+                                true
+                            }
                         }
                     }
                     HeapCellValue::Integer(ref n1) => {
-                        if let Constant::Integer(ref n2) = c {
-                            n1 != n2
-                        } else {
-                            true
+                        match c {
+                            Constant::Integer(ref n2) => {
+                                n1 != n2
+                            }
+                            Constant::Usize(n2) => {
+                                n1.to_usize() != Some(*n2)
+                            }
+                            _ => {
+                                true
+                            }
                         }
                     }
                     HeapCellValue::Rational(ref r1) => {
@@ -669,20 +809,32 @@ impl MachineState {
                             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)
+                    HeapCellValue::PartialString(..) => {
+                        if let Constant::String(ref s2) = c {
+                            let iter = self.heap_pstr_iter(Addr::PStrLocation(c1, 0));
+                            !compare_pstr(iter, s2.chars())
+                        } else {
+                            true
+                        }
                     }
                     _ => {
                         unreachable!()
                     }
                 };
             }
+            Addr::Char(ch) => {
+                self.fail = match c {
+                    Constant::Atom(ref n2, _) if n2.is_char() => {
+                        Some(ch) != n2.as_str().chars().next()
+                    }
+                    Constant::Char(c) => {
+                        *c != ch
+                    }
+                    _ => {
+                        true
+                    }
+                };
+            }
             Addr::EmptyList => {
                 if let Constant::EmptyList = c {
                 } else {
@@ -694,20 +846,23 @@ impl MachineState {
                 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
-                    }
-                }).unwrap_or(true);
+                self.fail = if let Constant::String(ref s2) = c {
+                    let iter = self.heap_pstr_iter(Addr::PStrLocation(h, n));
+                    !compare_pstr(iter, s2.chars())
+                } else {
+                    true
+                };
+            }
+            Addr::Stream(_) => {
+                self.fail = true;
             }
             addr => {
+                let c = self.heap.put_constant(c.clone());
+
                 if let Some(r) = addr.as_var() {
-                    let addr = self.heap.put_constant(c.clone());
-                    self.bind(r, addr);
+                    self.bind(r, c);
                 } else {
-                    self.fail = true;
+                    self.unify(addr, c);
                 }
             }
         };
@@ -1003,11 +1158,11 @@ impl MachineState {
     fn execute_fact_instr(&mut self, instr: &FactInstruction) {
         match instr {
             &FactInstruction::GetConstant(_, ref c, reg) => {
-                let addr = self[reg].clone();
+                let addr = self[reg];
                 self.write_constant_to_var(addr, c);
             }
             &FactInstruction::GetList(_, reg) => {
-                let addr = self.store(self.deref(self[reg].clone()));
+                let addr = self.store(self.deref(self[reg]));
 
                 match addr {
                     Addr::PStrLocation(h, n) => {
@@ -1032,9 +1187,9 @@ impl MachineState {
                 };
             }
             &FactInstruction::GetStructure(ref ct, arity, reg) => {
-                let addr = self.deref(self[reg].clone());
+                let addr = self.deref(self[reg]);
 
-                match self.store(addr.clone()) {
+                match self.store(addr) {
                     Addr::Str(a) => {
                         let result = &self.heap[a];
 
@@ -1062,11 +1217,11 @@ impl MachineState {
                 };
             }
             &FactInstruction::GetVariable(norm, arg) => {
-                self[norm] = self.registers[arg].clone();
+                self[norm] = self.registers[arg];
             }
             &FactInstruction::GetValue(norm, arg) => {
-                let norm_addr = self[norm].clone();
-                let reg_addr = self.registers[arg].clone();
+                let norm_addr = self[norm];
+                let reg_addr = self.registers[arg];
 
                 self.unify(norm_addr, reg_addr);
             }
@@ -1077,7 +1232,11 @@ impl MachineState {
                         self.write_constant_to_var(addr, c);
                     }
                     MachineMode::Write => {
-                        self.heap.put_constant(c.clone());
+                        let addr = self.heap.put_constant(c.clone());
+
+                        if !addr.is_heap_bound() {
+                            self.heap.push(HeapCellValue::Addr(addr));
+                        }
                     }
                 };
 
@@ -1099,11 +1258,11 @@ impl MachineState {
             &FactInstruction::UnifyLocalValue(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 => {
-                        let addr = self.deref(self[reg].clone());
+                        let addr = self.deref(self[reg]);
                         let h = self.heap.h();
 
                         if let Addr::HeapCell(hc) = addr {
@@ -1131,7 +1290,7 @@ impl MachineState {
                         self.unify(reg_addr, self.s.read(&self.heap));
                     }
                     MachineMode::Write => {
-                        let heap_val = self.store(self[reg].clone());
+                        let heap_val = self.store(self[reg]);
                         self.heap.push(HeapCellValue::Addr(heap_val));
                     }
                 };
@@ -1161,8 +1320,8 @@ impl MachineState {
                 let addr = self.store(self.deref(addr));
 
                 let offset = match addr {
-                    Addr::HeapCell(_) | Addr::StackCell(..)
-                  | Addr::AttrVar(..) | Addr::Stream(_) => {
+                    Addr::HeapCell(_) | Addr::StackCell(..) |
+                    Addr::AttrVar(..) | Addr::Stream(_) => {
                       v
                   }
                     Addr::PStrLocation(..) => {
@@ -1172,10 +1331,10 @@ impl MachineState {
                             c
                         }
                     }
-                    Addr::Char(_) | Addr::CharCode(_) | Addr::Con(_) | Addr::CutPoint(_)
-                        | Addr::EmptyList | Addr::Float(_) | Addr::Usize(_) => {
-                            c
-                        }
+                    Addr::Char(_) | Addr::CharCode(_) | Addr::Con(_) | Addr::CutPoint(_) |
+                    Addr::EmptyList | Addr::Float(_) | Addr::Usize(_) => {
+                        c
+                    }
                     Addr::Lis(_) => {
                         l
                     }
@@ -1212,7 +1371,7 @@ impl MachineState {
                 };
             }
             &IndexingInstruction::SwitchOnStructure(_, ref hm) => {
-                let a1 = self.registers[1].clone();
+                let a1 = self.registers[1];
                 let addr = self.store(self.deref(a1));
 
                 let offset = match addr {
@@ -1242,7 +1401,7 @@ impl MachineState {
     pub(super) fn execute_query_instr(&mut self, instr: &QueryInstruction) {
         match instr {
             &QueryInstruction::GetVariable(norm, arg) => {
-                self[norm] = self.registers[arg].clone();
+                self[norm] = self.registers[arg];
             }
             &QueryInstruction::PutConstant(_, ref c, reg) => {
                 self[reg] = self.heap.put_constant(c.clone());
@@ -1272,7 +1431,7 @@ impl MachineState {
                 }
             }
             &QueryInstruction::PutValue(norm, arg) => {
-                self.registers[arg] = self[norm].clone();
+                self.registers[arg] = self[norm];
             }
             &QueryInstruction::PutVariable(norm, arg) => {
                 match norm {
@@ -1292,7 +1451,11 @@ impl MachineState {
                 };
             }
             &QueryInstruction::SetConstant(ref c) => {
-                self.heap.put_constant(c.clone());
+                let addr = self.heap.put_constant(c.clone());
+
+                if !addr.is_heap_bound() {
+                    self.heap.push(HeapCellValue::Addr(addr));
+                }
             }
             &QueryInstruction::SetLocalValue(reg) => {
                 let addr = self.deref(self[reg]);
@@ -1312,7 +1475,7 @@ impl MachineState {
                 self[reg] = Addr::HeapCell(h);
             }
             &QueryInstruction::SetValue(reg) => {
-                let heap_val = self.store(self[reg].clone());
+                let heap_val = self.store(self[reg]);
                 self.heap.push(HeapCellValue::Addr(heap_val));
             }
             &QueryInstruction::SetVoid(n) => {
@@ -1328,7 +1491,7 @@ impl MachineState {
     pub(super) fn set_ball(&mut self) {
         self.ball.reset();
 
-        let addr = self[temp_v!(1)].clone();
+        let addr = self[temp_v!(1)];
         self.ball.boundary = self.heap.h();
 
         copy_term(
@@ -1340,10 +1503,10 @@ impl MachineState {
 
     pub(super) fn handle_internal_call_n(&mut self, arity: usize) {
         let arity = arity + 1;
-        let pred = self.registers[1].clone();
+        let pred = self.registers[1];
 
         for i in 2..arity {
-            self.registers[i - 1] = self.registers[i].clone();
+            self.registers[i - 1] = self.registers[i];
         }
 
         if arity > 1 {
@@ -1355,7 +1518,7 @@ impl MachineState {
     }
 
     pub(super) fn setup_call_n(&mut self, arity: usize) -> Option<PredicateKey> {
-        let addr = self.store(self.deref(self.registers[arity].clone()));
+        let addr = self.store(self.deref(self.registers[arity]));
 
         let (name, narity) = match addr {
             Addr::Str(a) => {
@@ -1375,7 +1538,7 @@ impl MachineState {
                     }
 
                     for i in (1 .. arity).rev() {
-                        self.registers[i + narity] = self.registers[i].clone();
+                        self.registers[i + narity] = self.registers[i];
                     }
 
                     for i in 1 .. narity + 1 {
@@ -1436,7 +1599,7 @@ impl MachineState {
         loop {
             if let Some(addr) = iter.stack().last() {
                 if !seen.contains(addr) {
-                    seen.insert(addr.clone());
+                    seen.insert(*addr);
                 } else {
                     fail = true;
                     break;
@@ -1452,7 +1615,8 @@ impl MachineState {
     }
 
     // arg(+N, +Term, ?Arg)
-    pub(super) fn try_arg(&mut self) -> CallResult {
+    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)]));
 
@@ -1480,7 +1644,7 @@ impl MachineState {
                         }
                     };
 
-                    let term = self.store(self.deref(self[temp_v!(2)].clone()));
+                    let term = self.store(self.deref(self[temp_v!(2)]));
 
                     match term {
                         Addr::HeapCell(_) | Addr::StackCell(..) => { // 8.5.2.3 b)
@@ -1488,16 +1652,18 @@ impl MachineState {
                         }
                         Addr::Str(o) => match self.heap.clone(o) {
                             HeapCellValue::NamedStr(arity, _, _) if 1 <= n && n <= arity => {
-                                let a3 = self[temp_v!(3)].clone();
+                                let a3 = self[temp_v!(3)];
                                 let h_a = Addr::HeapCell(o + n);
 
                                 self.unify(a3, h_a);
                             }
-                            _ => self.fail = true,
+                            _ => {
+                                self.fail = true;
+                            }
                         },
                         Addr::Lis(l) => {
                             if n == 1 || n == 2 {
-                                let a3 = self[temp_v!(3)].clone();
+                                let a3 = self[temp_v!(3)];
                                 let h_a = Addr::HeapCell(l + n - 1);
 
                                 self.unify(a3, h_a);
@@ -1507,9 +1673,9 @@ impl MachineState {
                         }
                         Addr::PStrLocation(h, offset) => {
                             if n == 1 || n == 2 {
-                                let a3 = self[temp_v!(3)].clone();
+                                let a3 = self[temp_v!(3)];
                                 let h_a =
-                                    if let HeapCellValue::PartialString(ref pstr) = &self.heap[h] {
+                                    if let HeapCellValue::PartialString(ref pstr, _) = &self.heap[h] {
                                         if let Some(c) = pstr.range_from(offset ..).next() {
                                             if n == 1 {
                                                 Addr::Char(c)
@@ -1544,7 +1710,7 @@ impl MachineState {
                         MachineError::type_error(
                             self.heap.h(),
                             ValidType::Integer,
-                            Addr::Con(h),
+                            Addr::HeapCell(h),
                         ),
                         stub,
                     ))
@@ -1582,8 +1748,8 @@ impl MachineState {
     }
 
     pub(super) fn compare_term(&mut self, qt: CompareTermQT) {
-        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)];
 
         match self.compare_term_test(&a1, &a2) {
             Some(Ordering::Greater) => match qt {
@@ -1625,7 +1791,7 @@ impl MachineState {
                     }
                 }
                 (Addr::PStrLocation(..), Addr::Lis(_))
-              | (Addr::Lis(_), Addr::PStrLocation(..)) 
+              | (Addr::Lis(_), Addr::PStrLocation(..))
                     if !self.flags.double_quotes.is_atom() => {
                         continue;
                     }
@@ -1674,6 +1840,36 @@ impl MachineState {
                         }
                     }
                 }
+                (Addr::Con(h), Addr::Char(c)) | (Addr::Char(c), Addr::Con(h)) => {
+                    match &self.heap[h] {
+                        &HeapCellValue::Atom(ref name, _) if name.is_char() => {
+                            if name.as_str().chars().next() != Some(c) {
+                                return true;
+                            }
+                        }
+                        _ => {
+                            return true;
+                        }
+                    }
+                }
+                (Addr::Usize(n1), Addr::Con(n2)) | (Addr::Con(n2), Addr::Usize(n1)) => {
+                    if let HeapCellValue::Integer(ref n2) = &self.heap[n2] {
+                        if let Some(n2) = n2.to_usize() {
+                            if n1 != n2 {
+                                return true;
+                            }
+                        }
+                    }
+                }
+                (Addr::CharCode(n1), Addr::Con(n2)) | (Addr::Con(n2), Addr::CharCode(n1)) => {
+                    if let HeapCellValue::Integer(ref n2) = &self.heap[n2] {
+                        if let Some(n2) = n2.to_u32() {
+                            if n1 == n2 {
+                                return true;
+                            }
+                        }
+                    }
+                }
                 (a1, a2) => {
                     if a1 != a2 {
                         return true;
@@ -1687,13 +1883,13 @@ impl MachineState {
     }
 
     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());
+        let mut iter = self.zipped_acyclic_pre_order_iter(*a1, *a2);
 
         while let Some((v1, v2)) = iter.next() {
             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 {
+            if order_cat_v1 != order_cat_v2 {
                 return Some(order_cat_v1.cmp(&order_cat_v2));
             }
 
@@ -1761,6 +1957,34 @@ impl MachineState {
                                 }
                             }
                         }
+                        (Addr::Usize(n1), Addr::Usize(n2)) => {
+                            if n1 != n2 {
+                                return Some(n1.cmp(&n2));
+                            }
+                        }
+                        (Addr::CharCode(n1), Addr::CharCode(n2)) => {
+                            if n1 != n2 {
+                                return Some(n1.cmp(&n2));
+                            }
+                        }
+                        (Addr::Usize(n1), Addr::Con(n2)) | (Addr::Con(n2), Addr::Usize(n1)) => {
+                            if let HeapCellValue::Integer(ref n2) = &self.heap[n2] {
+                                if let Some(n2) = n2.to_usize() {
+                                    if n1 != n2 {
+                                        return Some(n1.cmp(&n2));
+                                    }
+                                }
+                            }
+                        }
+                        (Addr::CharCode(n1), Addr::Con(n2)) | (Addr::Con(n2), Addr::CharCode(n1)) => {
+                            if let HeapCellValue::Integer(ref n2) = &self.heap[n2] {
+                                if let Some(n2) = n2.to_u32() {
+                                    if n1 != n2 {
+                                        return Some(n1.cmp(&n2));
+                                    }
+                                }
+                            }
+                        }
                         _ => {
                             unreachable!()
                         }
@@ -1956,6 +2180,11 @@ impl MachineState {
                                 Some('['.cmp(&c))
                             };
                         }
+                        (
+                            Addr::EmptyList,
+                            Addr::EmptyList,
+                        ) => {
+                        }
                         _ => {
                             return None;
                         }
@@ -2076,7 +2305,7 @@ impl MachineState {
                 self.compare_numbers(cmp, n1, n2);
             }
             &InlinedClauseType::IsAtom(r1) => {
-                let d = self.store(self.deref(self[r1].clone()));
+                let d = self.store(self.deref(self[r1]));
 
                 match d {
                     Addr::Con(h) =>
@@ -2091,7 +2320,7 @@ impl MachineState {
                 };
             }
             &InlinedClauseType::IsAtomic(r1) => {
-                let d = self.store(self.deref(self[r1].clone()));
+                let d = self.store(self.deref(self[r1]));
 
                 match d {
                     Addr::Con(_) => self.p += 1,
@@ -2099,7 +2328,7 @@ impl MachineState {
                 };
             }
             &InlinedClauseType::IsInteger(r1) => {
-                let d = self.store(self.deref(self[r1].clone()));
+                let d = self.store(self.deref(self[r1]));
 
                 match d {
                     Addr::Con(h) => {
@@ -2119,7 +2348,7 @@ impl MachineState {
                             }
                         }
                     }
-                    Addr::CharCode(_) => {
+                    Addr::CharCode(_) | Addr::Usize(_) => {
                         self.p += 1;
                     }
                     Addr::Char(_) if self.flags.double_quotes.is_codes() => {
@@ -2139,7 +2368,7 @@ impl MachineState {
                 };
             }
             &InlinedClauseType::IsFloat(r1) => {
-                let d = self.store(self.deref(self[r1].clone()));
+                let d = self.store(self.deref(self[r1]));
 
                 match d {
                     Addr::Float(_) => self.p += 1,
@@ -2147,7 +2376,7 @@ impl MachineState {
                 };
             }
             &InlinedClauseType::IsRational(r1) => {
-                let d = self.store(self.deref(self[r1].clone()));
+                let d = self.store(self.deref(self[r1]));
 
                 match d {
                     Addr::Con(h) => {
@@ -2163,7 +2392,7 @@ impl MachineState {
                 };
             }
             &InlinedClauseType::IsString(r1) => {
-                let d = self.store(self.deref(self[r1].clone()));
+                let d = self.store(self.deref(self[r1]));
 
                 match d {
                     Addr::PStrLocation(..) => self.p += 1,
@@ -2171,7 +2400,7 @@ impl MachineState {
                 };
             }
             &InlinedClauseType::IsNonVar(r1) => {
-                let d = self.store(self.deref(self[r1].clone()));
+                let d = self.store(self.deref(self[r1]));
 
                 match d {
                     Addr::AttrVar(_) | Addr::HeapCell(_) | Addr::StackCell(..) => {
@@ -2183,7 +2412,7 @@ impl MachineState {
                 };
             }
             &InlinedClauseType::IsVar(r1) => {
-                let d = self.store(self.deref(self[r1].clone()));
+                let d = self.store(self.deref(self[r1]));
 
                 match d {
                     Addr::AttrVar(_) | Addr::HeapCell(_) | Addr::StackCell(_, _) => {
@@ -2255,7 +2484,8 @@ impl MachineState {
             Addr::Stream(_) => {
                 self.fail = true;
             }
-            Addr::Char(_) | Addr::CharCode(_) | Addr::Con(_) | Addr::Float(_) => {
+            Addr::Char(_) | Addr::CharCode(_) | Addr::Con(_) | Addr::Float(_) |
+            Addr::EmptyList | Addr::Usize(_) => {
                 self.try_functor_unify_components(a1, 0);
             }
             Addr::Str(o) => match self.heap.clone(o) {
@@ -2280,10 +2510,36 @@ impl MachineState {
                     return Err(self.error_form(MachineError::instantiation_error(), stub));
                 }
 
-                if let Addr::Con(h) = arity {
-                    let arity = if let HeapCellValue::Integer(ref n) = &self.heap[h] {
-                        n.clone()
-                    } else {
+                let arity = match arity {
+                    Addr::Con(h) => {
+                        match &self.heap[h] {
+                            &HeapCellValue::Integer(ref n) => {
+                                n.to_isize()
+                            }
+                            &HeapCellValue::Addr(Addr::Usize(n)) => {
+                                Some(n as isize)
+                            }
+                            _ => {
+                                return Err(
+                                    self.error_form(
+                                        MachineError::type_error(
+                                            self.heap.h(),
+                                            ValidType::Integer,
+                                            arity,
+                                        ),
+                                        stub,
+                                    )
+                                );
+                            }
+                        }
+                    },
+                    Addr::Usize(n) => {
+                        Some(n as isize)
+                    }
+                    Addr::CharCode(c) => {
+                        Some(c as isize)
+                    }
+                    arity => {
                         return Err(
                             self.error_form(
                                 MachineError::type_error(
@@ -2294,95 +2550,87 @@ impl MachineState {
                                 stub,
                             )
                         );
-                    };
+                    }
+                };
 
-                    let arity = match arity.to_isize() {
-                        Some(arity) => arity,
-                        None => {
-                            self.fail = true;
-                            return Ok(());
-                        }
-                    };
+                let arity = match arity {
+                    Some(arity) => {
+                        arity
+                    }
+                    None => {
+                        self.fail = true;
+                        return Ok(());
+                    }
+                };
 
-                    if arity > MAX_ARITY as isize {
-                        // 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 = Number::Integer(Rc::new(Integer::from(arity)));
-                        let dom_err = MachineError::domain_error(
-                            DomainErrorType::NotLessThanZero,
-                            arity,
-                        );
+                if arity > MAX_ARITY as isize {
+                    // 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 = Number::Integer(Rc::new(Integer::from(arity)));
+                    let dom_err = MachineError::domain_error(
+                        DomainErrorType::NotLessThanZero,
+                        arity,
+                    );
 
-                        return Err(self.error_form(dom_err, stub));
-                    }
+                    return Err(self.error_form(dom_err, stub));
+                }
 
-                    match name {
-                        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) => {
+                match name {
+                    Addr::Char(_) | Addr::CharCode(_) | Addr::Con(_) | Addr::Float(_) |
+                    Addr::EmptyList | Addr::PStrLocation(..) | Addr::Usize(_) 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(
-                                clause_name!(c.to_string(), indices.atom_tbl),
+                                name,
                                 arity,
-                                None,
+                                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::Atomic, name),
+                                MachineError::type_error(
+                                    self.heap.h(),
+                                    ValidType::Atom,
+                                    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(
-                                self.heap.h(),
-                                ValidType::Integer,
-                                arity,
-                            ),
+                    Addr::Char(c) => {
+                        self.try_functor_fabricate_struct(
+                            clause_name!(c.to_string(), indices.atom_tbl),
+                            arity,
+                            None,
+                            &indices.op_dir,
+                            a1.as_var().unwrap(),
+                        );
+                    }
+                    _ => {
+                        return Err(self.error_form(
+                            MachineError::type_error(self.heap.h(), ValidType::Atomic, name),
                             stub,
-                        )
-                    );
+                        ));
+                    } // 8.5.1.3 c)
                 }
             }
             _ => {
                 self.fail = true;
             }
-        };
+        }
 
         Ok(())
     }
 
-    pub(super) fn term_dedup(&self, list: &mut Vec<Addr>) {
+    pub(super)
+    fn term_dedup(&self, list: &mut Vec<Addr>) {
         let mut result = vec![];
 
         for a2 in list.iter() {
@@ -2406,7 +2654,7 @@ impl MachineState {
     ) -> Result<Vec<Addr>, MachineStub> {
         let a1 = self.store(self.deref(self[r]));
 
-        match a1.clone() {
+        match a1 {
             Addr::Lis(l) => {
                 self.try_from_inner_list(vec![], l, caller, a1)
             }
@@ -2441,7 +2689,7 @@ impl MachineState {
         loop {
             match &self.heap[l] {
                 HeapCellValue::Addr(ref addr) =>
-                    match self.store(self.deref(addr.clone())) {
+                    match self.store(self.deref(*addr)) {
                         Addr::Lis(hcp) => {
                             result.push(self.heap[hcp].as_addr(hcp));
                             l = hcp + 1;
@@ -2486,9 +2734,13 @@ impl MachineState {
         a1: Addr,
     ) -> Result<Vec<Addr>, MachineStub> {
         loop {
-            if let HeapCellValue::PartialString(ref pstr) = &self.heap[h] {
+            if let &HeapCellValue::PartialString(ref pstr, has_tail) = &self.heap[h] {
                 chars.extend(pstr.range_from(n ..).map(Addr::Char));
 
+                if !has_tail {
+                    return Ok(chars);
+                }
+
                 let tail = self.heap[h + 1].as_addr(h + 1);
 
                 match self.store(self.deref(tail)) {
@@ -2499,6 +2751,8 @@ impl MachineState {
                         return self.try_from_inner_list(chars, l, caller, a1);
                     }
                     Addr::PStrLocation(h1, n1) => {
+                        chars.push(Addr::Char('\u{0}'));
+
                         h = h1;
                         n = n1;
                     }
@@ -2557,8 +2811,8 @@ impl MachineState {
     pub(super) fn copy_term(&mut self, attr_var_policy: AttrVarPolicy) {
         let old_h = self.heap.h();
 
-        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)];
 
         copy_term(CopyTerm::new(self), a1, attr_var_policy);
 
@@ -2650,9 +2904,13 @@ impl MachineState {
                         }
                     },
                 (
-                    HeapCellValue::PartialString(ref pstr1),
-                    HeapCellValue::PartialString(ref pstr2),
+                    HeapCellValue::PartialString(ref pstr1, has_tail_1),
+                    HeapCellValue::PartialString(ref pstr2, has_tail_2),
                 ) => {
+                    if has_tail_1 != has_tail_2 {
+                        return true;
+                    }
+
                     let pstr1_iter = pstr1.range_from(0 ..);
                     let pstr2_iter = pstr2.range_from(0 ..);
 
@@ -2731,7 +2989,7 @@ impl MachineState {
     // returns true on failure.
     pub(super)
     fn ground_test(&self) -> bool {
-        let a = self.store(self.deref(self[temp_v!(1)].clone()));
+        let a = self.store(self.deref(self[temp_v!(1)]));
 
         for v in self.acyclic_pre_order_iter(a) {
             match v {
@@ -2895,7 +3153,7 @@ impl MachineState {
                 self.p += offset;
             }
             &ControlInstruction::Proceed => {
-                self.p = CodePtr::Local(self.cp.clone());
+                self.p = CodePtr::Local(self.cp);
             }
         };
     }
@@ -2928,7 +3186,7 @@ impl MachineState {
                 self.b = b;
 
                 for i in 1 .. n + 1 {
-                    self.stack.index_or_frame_mut(b)[i-1] = self.registers[i].clone();
+                    self.stack.index_or_frame_mut(b)[i-1] = self.registers[i];
                 }
 
                 self.hb = self.heap.h();
@@ -2966,7 +3224,7 @@ impl MachineState {
                 self.b = b;
 
                 for i in 1 .. n + 1  {
-                    self.stack.index_or_frame_mut(b)[i-1] = self.registers[i].clone();
+                    self.stack.index_or_frame_mut(b)[i-1] = self.registers[i];
                 }
 
                 self.hb = self.heap.h();
@@ -3015,8 +3273,8 @@ impl MachineState {
                 self.p += 1;
             }
             &CutInstruction::GetLevelAndUnify(r) => {
-                let b0 = self[perm_v!(1)].clone();
-                let a = self[r].clone();
+                let b0 = self[perm_v!(1)];
+                let a = self[r];
 
                 self.unify(a, b0);
                 self.p += 1;
index 320150308977a6192e2809253e1a17eeb9d70ca1..0a74ecff7f84783b29ef7b0bdf161c8ff7edf90a 100644 (file)
@@ -1,11 +1,28 @@
+use core::marker::PhantomData;
+
 use std::alloc;
 use std::mem;
 use std::ptr;
-use std::ops::{Range, RangeFrom};
+use std::ops::RangeFrom;
+use std::slice;
 use std::str;
 
 pub struct PartialString {
     buf: *const u8,
+    len: usize,
+    _marker: PhantomData<[u8]>,
+}
+
+impl Drop for PartialString {
+    fn drop(&mut self) {
+        unsafe {
+            let layout = alloc::Layout::from_size_align_unchecked(self.len, mem::align_of::<u8>());
+            alloc::dealloc(self.buf as *mut u8, layout);
+
+            self.buf = ptr::null();
+            self.len = 0;
+        }
+    }
 }
 
 impl Clone for PartialString {
@@ -47,54 +64,31 @@ impl Iterator for PStrIter {
 
     fn next(&mut self) -> Option<Self::Item> {
         unsafe {
-            let b = ptr::read(self.buf);
-
-            if b == 0u8 {
-                return None;
-            }
+            let mut byte_count = 0;
 
-            let c = ptr::read(self.buf as *const char);
-            self.buf = self.buf.offset(c.len_utf8() as isize);
+            for n in 0 .. mem::size_of::<char>() {
+                let b = ptr::read((self.buf as usize + n) as *const u8);
 
-            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;
+                if b == 0u8 {
+                    break;
+                } else {
+                    byte_count += 1;
+                }
             }
 
-            let b = ptr::read(self.buf);
-
-            if b == 0u8 {
+            if byte_count == 0 {
                 return None;
             }
 
-            let c = ptr::read(self.buf as *const char);
-            self.buf = self.buf.offset(c.len_utf8() as isize);
+            let slice = slice::from_raw_parts(self.buf, byte_count);
+            let s = str::from_utf8(slice).unwrap();
 
-            Some(c)
+            if let Some(c) = s.chars().next() {
+                self.buf = self.buf.offset(c.len_utf8() as isize);
+                Some(c)
+            } else {
+                None
+            }
         }
     }
 }
@@ -105,6 +99,8 @@ impl PartialString {
     fn new(src: &str) -> Option<(Self, &str)> {
         let pstr = PartialString {
             buf: ptr::null_mut(),
+            len: 0,
+            _marker: PhantomData,
         };
 
         unsafe {
@@ -116,7 +112,9 @@ impl PartialString {
     pub(super)
     fn empty() -> Self {
         PartialString {
-            buf: "\u{0}".as_bytes()[0] as *const _,
+            buf: &"\u{0}".as_bytes()[0] as *const _,
+            len: '\u{0}'.len_utf8(),
+            _marker: PhantomData,
         }
     }
 
@@ -128,11 +126,12 @@ impl PartialString {
         }
 
         let layout = alloc::Layout::from_size_align_unchecked(
-            src.len() + '\u{0}'.len_utf8(),
+            terminator_idx + '\u{0}'.len_utf8(),
             mem::align_of::<u8>(),
         );
 
         self.buf = alloc::alloc(layout) as *const _;
+        self.len = terminator_idx + '\u{0}'.len_utf8();
 
         ptr::copy(
             src.as_ptr(),
@@ -149,24 +148,17 @@ impl PartialString {
         })
     }
 
-    #[inline]
-    pub(crate)
-    fn iter(&self) -> PStrIter {
-        PStrIter {
-            buf: self.buf,
-        }
-    }
-
     pub(super)
     fn clone_from_offset(&self, n: usize) -> Self {
+        let len = if self.len > n { self.len - n } else { 0 };
+
         let mut pstr = PartialString {
             buf: ptr::null_mut(),
+            len: len + '\u{0}'.len_utf8(),
+            _marker: PhantomData,
         };
 
         unsafe {
-            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>(),
@@ -199,11 +191,6 @@ impl PartialString {
         }
     }
 
-    #[inline]
-    pub fn range(&self, index: Range<usize>) -> PStrIterBounded {
-        PStrIterBounded::from(self.buf, index.start, index.end)
-    }
-
     #[inline]
     pub fn range_from(&self, index: RangeFrom<usize>) -> PStrIter {
         PStrIter::from(self.buf, index.start)
index 3ae383d5762b5ae703c984a36f75f3b0bd382e82..64135048eb79bacb8066d7773054f80e57d15195 100644 (file)
@@ -5,7 +5,7 @@ use std::mem;
 use std::ptr;
 
 pub(crate) trait RawBlockTraits {
-    fn init_size() -> usize;    
+    fn init_size() -> usize;
     fn align() -> usize;
 
     #[inline]
@@ -36,20 +36,6 @@ impl<T: RawBlockTraits> RawBlock<T> {
         block
     }
 
-    pub(crate)
-    fn with_capacity(cap: usize) -> Self {
-        let mut block = RawBlock { size: 0,
-                                   base: ptr::null(),
-                                   top: ptr::null(),
-                                   _marker: PhantomData };
-
-        unsafe {
-            block.init_at_size(cap);
-        }
-
-        block
-    }
-
     unsafe fn init_at_size(&mut self, cap: usize) {
         let layout = alloc::Layout::from_size_align_unchecked(cap, T::align());
 
@@ -86,7 +72,6 @@ impl<T: RawBlockTraits> RawBlock<T> {
         mem::replace(self, Self::empty_block())
     }
 
-
     #[inline]
     fn free_space(&self) -> usize {
         debug_assert!(self.top >= self.base,
index 6e0731d51b4c48867756771c87846dbf46fa0c7e..e2602e721d808ff9e1e50fa16174a03a857c349b 100644 (file)
@@ -49,7 +49,6 @@ impl Drop for Stack {
 
 #[derive(Clone, Copy)]
 pub struct FramePrelude {
-    is_or_frame: u8,
     pub num_cells: usize,
 }
 
@@ -62,7 +61,6 @@ pub struct AndFramePrelude {
 
 pub struct AndFrame {
     pub prelude: AndFramePrelude,
-    _marker: PhantomData<Addr>,
 }
 
 impl AndFrame {
@@ -89,8 +87,6 @@ impl Index<usize> for AndFrame {
 
 impl IndexMut<usize> for AndFrame {
     fn index_mut(&mut self, index: usize) -> &mut Self::Output {
-        debug_assert!(self.prelude.univ_prelude.is_or_frame == 0);
-
         let prelude_offset = prelude_size::<AndFramePrelude>();
         let index_offset = (index - 1) * mem::size_of::<Addr>();
 
@@ -103,24 +99,6 @@ impl IndexMut<usize> for AndFrame {
     }
 }
 
-impl Drop for AndFrame {
-    fn drop(&mut self) {
-        let prelude_offset = prelude_size::<AndFramePrelude>();
-
-        unsafe {
-            let ptr = mem::transmute::<&mut AndFrame, *const u8>(self);
-            let ptr = ptr as usize + prelude_offset;
-
-            for idx in 0 .. self.prelude.univ_prelude.num_cells {
-                let index_offset = idx * mem::size_of::<Addr>();
-                let ptr = (ptr + index_offset) as *mut Addr;
-
-                ptr::drop_in_place(ptr);
-            }
-        }
-    }
-}
-
 pub struct OrFramePrelude {
     pub univ_prelude: FramePrelude,
     pub e: usize,
@@ -137,7 +115,6 @@ pub struct OrFramePrelude {
 
 pub struct OrFrame {
     pub prelude: OrFramePrelude,
-    _marker: PhantomData<Addr>
 }
 
 impl Index<usize> for OrFrame {
@@ -145,8 +122,6 @@ impl Index<usize> for OrFrame {
 
     #[inline]
     fn index(&self, index: usize) -> &Self::Output {
-        debug_assert!(self.prelude.univ_prelude.is_or_frame == 1);
-
         let prelude_offset = prelude_size::<OrFramePrelude>();
         let index_offset = index * mem::size_of::<Addr>();
 
@@ -162,8 +137,6 @@ impl Index<usize> for OrFrame {
 impl IndexMut<usize> for OrFrame {
     #[inline]
     fn index_mut(&mut self, index: usize) -> &mut Self::Output {
-        debug_assert!(self.prelude.univ_prelude.is_or_frame == 1);
-
         let prelude_offset = prelude_size::<OrFramePrelude>();
         let index_offset = index * mem::size_of::<Addr>();
 
@@ -176,24 +149,6 @@ impl IndexMut<usize> for OrFrame {
     }
 }
 
-impl Drop for OrFrame {
-    fn drop(&mut self) {
-        let prelude_offset = prelude_size::<OrFramePrelude>();
-
-        unsafe {
-            let ptr = mem::transmute::<&mut OrFrame, *const u8>(self);
-            let ptr = ptr as usize + prelude_offset;
-
-            for idx in 0 .. self.prelude.univ_prelude.num_cells {
-                let index_offset = idx * mem::size_of::<Addr>();
-                let ptr = (ptr + index_offset) as *mut Addr;
-
-                ptr::drop_in_place(ptr);
-            }
-        }
-    }
-}
-
 impl OrFrame {
     pub fn size_of(num_cells: usize) -> usize {
         prelude_size::<OrFramePrelude>() + num_cells * mem::size_of::<Addr>()
@@ -217,8 +172,6 @@ impl Stack {
             }
 
             let and_frame = &mut *(self.buf.top as *mut AndFrame);
-
-            and_frame.prelude.univ_prelude.is_or_frame = 0;
             and_frame.prelude.univ_prelude.num_cells = num_cells;
 
             let e = self.buf.top as usize - self.buf.base as usize;
@@ -240,8 +193,6 @@ impl Stack {
             }
 
             let or_frame = &mut *(self.buf.top as *mut OrFrame);
-
-            or_frame.prelude.univ_prelude.is_or_frame = 1;
             or_frame.prelude.univ_prelude.num_cells = num_cells;
 
             let b = self.buf.top as usize - self.buf.base as usize;
@@ -287,6 +238,7 @@ impl Stack {
         Stack { buf: self.buf.take(), _marker: PhantomData }
     }
 
+    #[inline]
     pub fn truncate(&mut self, b: usize) {
         if b == 0 {
             self.inner_truncate(mem::align_of::<Addr>());
@@ -295,40 +247,12 @@ impl Stack {
         }
     }
 
+    #[inline]
     fn inner_truncate(&mut self, b: usize) {
-        let mut b = b + self.buf.base as usize;
-        let base  = b;
+        let base = b + self.buf.base as usize;
 
-        unsafe {
-            while b as *const _ < self.buf.top {
-                let univ_prelude = ptr::read(b as *const FramePrelude);
-
-                let offset = if univ_prelude.is_or_frame == 0 {
-                    let frame_ptr = b as *mut AndFrame;
-                    let frame = &mut *frame_ptr;
-                    let size_of_frame = AndFrame::size_of(frame.prelude.univ_prelude.num_cells);
-
-                    ptr::drop_in_place(frame_ptr);
-
-                    b + size_of_frame
-                } else {
-                    debug_assert!(univ_prelude.is_or_frame == 1);
-
-                    let frame_ptr = b as *mut OrFrame;
-                    let frame = &mut *frame_ptr;
-                    let size_of_frame = OrFrame::size_of(frame.prelude.univ_prelude.num_cells);
-
-                    ptr::drop_in_place(frame_ptr);
-
-                    b + size_of_frame
-                };
-
-                b = offset;
-            }
-
-            if base < self.buf.top as usize {
-                self.buf.top = base as *const _;
-            }
+        if base < self.buf.top as usize {
+            self.buf.top = base as *const _;
         }
     }
 
index 9f927da249ec7aa186a2867e00fe3b015b174c6f..dbbc25e517654b1719303fb34d456122f1497024 100644 (file)
@@ -77,7 +77,7 @@ struct BrentAlgState {
 impl BrentAlgState {
     fn new(hare: Addr) -> Self {
         BrentAlgState {
-            hare: hare.clone(),
+            hare: hare,
             tortoise: hare,
             power: 2,
             steps: 0,
@@ -89,7 +89,7 @@ impl BrentAlgState {
         if self.tortoise == self.hare {
             return Some(CycleSearchResult::NotList);
         } else if self.steps == self.power {
-            self.tortoise = self.hare.clone();
+            self.tortoise = self.hare;
             self.power <<= 1;
         }
 
@@ -144,7 +144,7 @@ impl MachineState {
             }
             Addr::PStrLocation(h, n) => {
                 match &self.heap[h] {
-                    HeapCellValue::PartialString(ref pstr) => {
+                    HeapCellValue::PartialString(ref pstr, _) => {
                         if let Some(c) = pstr.range_from(n ..).next() {
                             brent_st.step(Addr::PStrLocation(h, n + c.len_utf8()))
                         } else {
@@ -184,7 +184,7 @@ impl MachineState {
                 return CycleSearchResult::EmptyList;
             }
             Addr::Con(h) if max_steps > 0 => {
-                if let HeapCellValue::PartialString(_) = &self.heap[h] {
+                if let HeapCellValue::PartialString(..) = &self.heap[h] {
                     if !self.flags.double_quotes.is_atom() {
                         Addr::PStrLocation(h, 0)
                     } else {
@@ -195,7 +195,7 @@ impl MachineState {
                 }
             }
             Addr::Con(h) => {
-                if let HeapCellValue::PartialString(_) = &self.heap[h] {
+                if let HeapCellValue::PartialString(..) = &self.heap[h] {
                     if !self.flags.double_quotes.is_atom() {
                         return CycleSearchResult::UntouchedList(h);
                     }
@@ -235,7 +235,7 @@ impl MachineState {
                 Addr::PStrLocation(h, n)
             }
             Addr::Con(h) => {
-                if let HeapCellValue::PartialString(_) = &self.heap[h] {
+                if let HeapCellValue::PartialString(..) = &self.heap[h] {
                     if !self.flags.double_quotes.is_atom() {
                         Addr::PStrLocation(h, 0)
                     } else {
@@ -425,7 +425,7 @@ impl MachineState {
             &indices.op_dir,
         ) {
             Ok(term_write_result) => {
-                let a1 = self[temp_v!(1)].clone();
+                let a1 = self[temp_v!(1)];
                 self.unify(Addr::HeapCell(term_write_result.heap_loc), a1);
 
                 if self.fail {
@@ -447,7 +447,7 @@ impl MachineState {
                     list_of_var_eqs.push(Addr::Str(h));
                 }
 
-                let a2 = self[temp_v!(2)].clone();
+                let a2 = self[temp_v!(2)];
                 let list_offset =
                     Addr::HeapCell(self.heap.to_list(list_of_var_eqs.into_iter()));
 
@@ -475,7 +475,7 @@ impl MachineState {
         self.block = self.b;
 
         let c = Constant::Usize(self.block);
-        let addr = self[r].clone();
+        let addr = self[r];
 
         self.write_constant_to_var(addr, &c);
         self.block
@@ -513,7 +513,7 @@ impl MachineState {
     where
         AddrConstr: Fn(usize) -> Addr,
     {
-        match self.store(self.deref(self[temp_v!(1)].clone())) {
+        match self.store(self.deref(self[temp_v!(1)])) {
             Addr::Usize(lh_offset) => {
                 if lh_offset >= self.lifted_heap.h() {
                     self.lifted_heap.truncate(lh_offset);
@@ -542,7 +542,7 @@ impl MachineState {
                         continue;
                     }
 
-                    let a2 = self[temp_v!(2)].clone();
+                    let a2 = self[temp_v!(2)];
 
                     if let Some(r) = a2.as_var() {
                         let spec = get_clause_spec(
@@ -578,7 +578,7 @@ impl MachineState {
 
                 match op_dir.range(key..).skip(1).next() {
                     Some((OrderedOpDirKey(name, _), (priority, spec))) => {
-                        let a2 = self[temp_v!(2)].clone();
+                        let a2 = self[temp_v!(2)];
 
                         if let Some(r) = a2.as_var() {
                             let addr = self.heap.to_unifiable(
@@ -627,7 +627,7 @@ impl MachineState {
         indices: &IndexStore,
         stub: MachineStub,
     ) -> CallResult {
-        let nx = self[temp_v!(2)].clone();
+        let nx = self[temp_v!(2)];
 
         if let Some(c) = string.chars().last() {
             if layout_char!(c) {
@@ -696,7 +696,7 @@ impl MachineState {
         self.term_dedup(&mut attr_goals);
 
         let attr_goals = Addr::HeapCell(self.heap.to_list(attr_goals.into_iter()));
-        let target = self[temp_v!(1)].clone();
+        let target = self[temp_v!(1)];
 
         self.unify(attr_goals, target);
     }
@@ -773,7 +773,7 @@ impl MachineState {
                 return Ok(());
             }
             &SystemClauseType::BindFromRegister => {
-                let reg = self.store(self.deref(self[temp_v!(2)].clone()));
+                let reg = self.store(self.deref(self[temp_v!(2)]));
                 let n = match reg {
                     Addr::Con(h) =>
                         if let HeapCellValue::Integer(ref n) = &self.heap[h] {
@@ -781,13 +781,15 @@ impl MachineState {
                         } else {
                             unreachable!()
                         }
-                    _ => unreachable!()
+                    _ => {
+                        unreachable!()
+                    }
                 };
 
                 if let Some(n) = n {
                     if n <= MAX_ARITY {
-                        let target = self[temp_v!(n)].clone();
-                        let addr   = self[temp_v!(1)].clone();
+                        let target = self[temp_v!(n)];
+                        let addr   = self[temp_v!(1)];
 
                         self.unify(addr, target);
                         return return_from_clause!(self.last_call, self);
@@ -843,7 +845,7 @@ impl MachineState {
                 }
             }
             &SystemClauseType::CurrentOutput => {
-                let addr = self.store(self.deref(self[temp_v!(1)].clone()));
+                let addr = self.store(self.deref(self[temp_v!(1)]));
                 let stream = current_output_stream.clone();
 
                 match addr {
@@ -879,7 +881,7 @@ impl MachineState {
                 }
             }
             &SystemClauseType::AtomChars => {
-                let a1 = self[temp_v!(1)].clone();
+                let a1 = self[temp_v!(1)];
 
                 match self.store(self.deref(a1)) {
                     Addr::Char(c) => {
@@ -890,7 +892,7 @@ impl MachineState {
                         self.unify(a2, list_of_chars);
                     }
                     Addr::Con(h) if self.heap.atom_at(h) => {
-                       if let HeapCellValue::Atom(name, _) = self.heap.clone(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));
 
@@ -910,7 +912,7 @@ impl MachineState {
                         }
                     }
                     Addr::EmptyList => {
-                        let a2 = self[temp_v!(2)].clone();
+                        let a2 = self[temp_v!(2)];
                         let chars = vec![
                             Addr::Char('['),
                             Addr::Char(']'),
@@ -954,14 +956,14 @@ impl MachineState {
                 };
             }
             &SystemClauseType::AtomCodes => {
-                let a1 = self[temp_v!(1)].clone();
+                let a1 = self[temp_v!(1)];
 
                 match self.store(self.deref(a1)) {
                     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();
+                        let a2 = self[temp_v!(2)];
                         self.unify(a2, list_of_codes);
                     }
                     Addr::Con(h) if self.heap.atom_at(h) => {
@@ -1005,7 +1007,7 @@ impl MachineState {
                         ];
 
                         let list_of_codes = Addr::HeapCell(self.heap.to_list(chars.into_iter()));
-                        let a2 = self[temp_v!(2)].clone();
+                        let a2 = self[temp_v!(2)];
 
                         self.unify(a2, list_of_codes);
                     }
@@ -1170,7 +1172,7 @@ impl MachineState {
                 }
             }
             &SystemClauseType::IsPartialString => {
-                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(..) => {
@@ -1289,7 +1291,7 @@ impl MachineState {
                 return Ok(());
             }
             &SystemClauseType::LiftedHeapLength => {
-                let a1 = self[temp_v!(1)].clone();
+                let a1 = self[temp_v!(1)];
                 let lh_len = Addr::Usize(self.lifted_heap.h());
 
                 self.unify(a1, lh_len);
@@ -1350,7 +1352,7 @@ impl MachineState {
                 };
             }
             &SystemClauseType::CheckCutPoint => {
-                let addr = self.store(self.deref(self[temp_v!(1)].clone()));
+                let addr = self.store(self.deref(self[temp_v!(1)]));
 
                 match addr {
                     Addr::Usize(old_b) | Addr::CutPoint(old_b) => {
@@ -1400,7 +1402,7 @@ impl MachineState {
                 };
             }
             &SystemClauseType::FetchGlobalVarWithOffset => {
-                let key = self[temp_v!(1)].clone();
+                let key = self[temp_v!(1)];
 
                 let key = match self.store(self.deref(key)) {
                     Addr::Con(h) if self.heap.atom_at(h) => {
@@ -1428,7 +1430,7 @@ impl MachineState {
                         *offset = Some(h);
                     }
                     Some((_, Some(h))) => {
-                        let offset = self[temp_v!(3)].clone();
+                        let offset = self[temp_v!(3)];
 
                         self.unify(offset, Addr::Usize(*h));
 
@@ -1445,7 +1447,7 @@ impl MachineState {
                 let mut iter = parsing_stream(current_input_stream.clone());
                 let result = iter.next();
 
-                let a1 = self[temp_v!(1)].clone();
+                let a1 = self[temp_v!(1)];
 
                 match result {
                     Some(Ok(b)) => {
@@ -1559,7 +1561,7 @@ impl MachineState {
                 };
             }
             &SystemClauseType::HeadIsDynamic => {
-                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] {
@@ -1595,7 +1597,7 @@ impl MachineState {
                         for addr in self.lifted_heap.iter_mut_from(old_threshold + 1) {
                             match addr {
                                 HeapCellValue::Addr(ref mut addr) => {
-                                    *addr -= self.heap.h() + lh_offset
+                                    *addr -= self.heap.h() + lh_offset;
                                 }
                                 _ => {}
                             }
@@ -2094,7 +2096,7 @@ impl MachineState {
                                 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);
                             } else {
@@ -2416,7 +2418,7 @@ impl MachineState {
                                 ),
                             );
 
-                            let target = self[temp_v!(1)].clone();
+                            let target = self[temp_v!(1)];
 
                             self.unify(target, module);
                         }
@@ -2885,7 +2887,7 @@ impl MachineState {
                     ContinueResult::PrintWithMaxDepth => 'p',
                 };
 
-                let target = self[temp_v!(1)];                
+                let target = self[temp_v!(1)];
                 self.unify(Addr::Char(c), target);
             }
             &SystemClauseType::NextEP => {
@@ -3008,12 +3010,12 @@ impl MachineState {
                 self.reset_block(addr);
             }
             &SystemClauseType::ResetContinuationMarker => {
-                let h = self.heap.h();
-
                 self[temp_v!(3)] = self.heap.to_unifiable(
                     HeapCellValue::Atom(clause_name!("none"), None)
                 );
 
+                let h = self.heap.h();
+
                 self.heap.push(HeapCellValue::Addr(Addr::HeapCell(h)));
                 self[temp_v!(4)] = Addr::HeapCell(h);
             }
@@ -3079,7 +3081,7 @@ impl MachineState {
                 let mut ball = Ball::new();
 
                 ball.boundary = self.heap.h();
-                
+
                 copy_term(
                     CopyBallTerm::new(&mut self.stack, &mut self.heap, &mut ball.stub),
                     value,
@@ -3238,7 +3240,7 @@ impl MachineState {
                             h,
                             ExistenceError::Procedure(name, arity),
                         );
-                        
+
                         let err = self.error_form(err, stub);
 
                         self.throw_exception(err);
@@ -3262,7 +3264,7 @@ impl MachineState {
                 );
 
                 let listing = Addr::HeapCell(self.heap.to_list(functors.into_iter()));
-                let listing_var = self[temp_v!(3)].clone();
+                let listing_var = self[temp_v!(3)];
 
                 self.unify(listing, listing_var);
             }
index 94ad5951765dd2e439cf7aa216539712b535576a..2af0c13f109b83d577f8410a85dca66cfdd5044b 100644 (file)
@@ -235,7 +235,7 @@ impl<'a> TermStream<'a> {
 
         while let Some(term) = self.stack.pop() {
             match machine_st.try_expand_term(self.wam, &term, CompileTimeHook::TermExpansion) {
-                Some(term_string) => {                        
+                Some(term_string) => {
                     let term = self.parse_expansion_output(term_string.as_str(), op_dir)?;
                     self.enqueue_term(term)?;
                 }
@@ -247,7 +247,7 @@ impl<'a> TermStream<'a> {
 
         unreachable!()
     }
-    
+
     pub fn read_term(&mut self, op_dir: &OpDir) -> Result<Term, ParserError> {
         loop {
             if let Some(term) = self.stack.pop() {
@@ -304,7 +304,8 @@ impl<'a> TermStream<'a> {
 }
 
 impl MachineState {
-    pub(super) fn print_with_locs(&self, addr: Addr, op_dir: &OpDir) -> PrinterOutputter {
+    pub(super)
+    fn print_with_locs(&self, addr: Addr, op_dir: &OpDir) -> PrinterOutputter {
         let output = PrinterOutputter::new();
         let mut printer = HCPrinter::from_heap_locs(&self, op_dir, output);
         let mut max_var_length = 0;
@@ -315,12 +316,14 @@ impl MachineState {
 
         printer.quoted = true;
         printer.numbervars = true;
-        
-        // the purpose of the offset is to avoid clashes with variable names that might
-        // occur after the addresses in the expanded term are substituted with the variable
-        // names in the pre-expansion term. This formula ensures that all generated "numbervars"-
-        // style variable names will be longer than the keys of the var_dict, and therefore
-        // not equal to any of them.
+
+        // the purpose of the offset is to avoid clashes with variable
+        // names that might occur after the addresses in the expanded
+        // term are substituted with the variable names in the
+        // pre-expansion term. This formula ensures that all generated
+        // "numbervars"- style variable names will be longer than the
+        // keys of the var_dict, and therefore not equal to any of
+        // them.
         printer.numbervars_offset = Integer::from(10).pow(max_var_length as u32) * 26;
         printer.print_strings_as_strs = true;
         printer.drop_toplevel_spec();
@@ -334,8 +337,8 @@ impl MachineState {
     }
 
     // reset the machine, but keep the heap contents as they were.
-    // this prevents clashes between underscored variable names
-    // in the same query.
+    // this prevents clashes between underscored variable names in the
+    // same query.
     fn reset_with_heap_preservation(&mut self) {
         let heap = self.heap.take();
         self.reset();
@@ -359,7 +362,9 @@ impl MachineState {
         wam.code_repo.cached_query = code;
 
         self.cp = LocalCodePtr::TopLevel(0, 0);
+        
         self.at_end_of_expansion = false;
+        self.flags.double_quotes = DoubleQuotes::Chars;
 
         self.query_stepper(
             &mut wam.indices,
index c08532dd9f0d835d2966e1787ab12d99235792f8..1ba6e07ae3e0417f203f7f1c02e112cf3318d760 100644 (file)
@@ -112,16 +112,6 @@ macro_rules! functor_term {
     (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)))
     );
@@ -148,9 +138,6 @@ macro_rules! from_constant {
             &Constant::CharCode(c) => {
                 HeapCellValue::Addr(Addr::CharCode(c))
             }
-            &Constant::CutPoint(cp) => {
-                HeapCellValue::Addr(Addr::CutPoint(cp))
-            }
             &Constant::Integer(ref n) => {
                 HeapCellValue::Integer(n.clone())
             }
index 33bea7cd0ee88177fdc07accef36106e7350b17f..af70cd0291518a586772f2b04a9d39ffa76bdd83 100644 (file)
@@ -153,7 +153,8 @@ pub struct TermWriteResult {
     pub(crate) var_dict: HeapVarDict,
 }
 
-pub(crate) fn write_term_to_heap(term: &Term, machine_st: &mut MachineState) -> TermWriteResult {
+pub(crate)
+fn write_term_to_heap(term: &Term, machine_st: &mut MachineState) -> TermWriteResult {
     let heap_loc = machine_st.heap.h();
 
     let mut queue = SubtermDeque::new();
@@ -188,13 +189,13 @@ pub(crate) fn write_term_to_heap(term: &Term, machine_st: &mut MachineState) ->
                     continue;
                 }
             }
-            &TermRef::AnonVar(Level::Root) | &TermRef::Constant(Level::Root, ..) => {
-                let value = HeapCellValue::Addr(term.as_addr(&mut machine_st.heap, h));
-                machine_st.heap.push(value);
-            }
-            &TermRef::Var(Level::Root, ..) => {
-                let value = HeapCellValue::Addr(term.as_addr(&mut machine_st.heap, h));
-                machine_st.heap.push(value);
+            &TermRef::AnonVar(Level::Root) | &TermRef::Constant(Level::Root, ..)
+          | &TermRef::Var(Level::Root, ..) => {
+                let addr = term.as_addr(&mut machine_st.heap, h);
+
+                if !addr.is_heap_bound() {
+                    machine_st.heap.push(HeapCellValue::Addr(addr));
+                }
             }
             &TermRef::AnonVar(_) => {
                 if let Some((arity, site_h)) = queue.pop_front() {
index 73011c35a4ab33b60f0880d5c9c502b1145173af..d4437fdd4ec9a32821cef9410997b1267b0928bf 100644 (file)
@@ -43,7 +43,6 @@
     ).
 
 '$submit_query_and_print_results'(Term0, VarList) :-
-    write('oh brother'), nl,
     (  expand_goals(Term0, Term) -> true
     ;  Term0 = Term
     ),
index e3e018c79e5b2c7474cbbe8489a92c153931b16d..a1d8bb976d10865899ba39dd9a6c3f66004b527b 100644 (file)
@@ -158,8 +158,10 @@ impl fmt::Display for HeapCellValue {
             &HeapCellValue::NamedStr(arity, ref name, None) => {
                 write!(f, "{}/{}", name.as_str(), arity)
             }
-            &HeapCellValue::PartialString(ref pstr) => {
-                write!(f, "pstr ( buf: 0x{:x} )", (pstr as *const _) as usize)
+            &HeapCellValue::PartialString(ref pstr, has_tail) => {
+                write!(f, "pstr ( buf: 0x{:x}, has_tail({}) )",
+                       (pstr as *const _) as usize,
+                       has_tail)
             }
             &HeapCellValue::Stream(ref stream) => {
                 write!(f, "$stream({})", stream.as_ptr() as usize)
index a81f681429e0030342ea0d8997e2cb6fe6cad95b..762fca97df0f5c5680b4d2927edc7ffc0f7d3eee 100644 (file)
@@ -23,6 +23,6 @@ test_queries_on_facts :-
     retract(p(_,_,_)),
     assertz(p(Z, h(Z, W), f(W))),
     p(f(f(a)), h(f(f(a)), f(a)), f(f(a))),
-    retract(p(Z, h(Z, W), f(W))).
+    retract(p(Z, h(Z, W), f(W))).[
 
 :- initialization(test_queries_on_facts).