]> Repositorios git - scryer-prolog.git/commitdiff
use printer cycle detection when printing partial strings (#1263), refactor skip_max_...
authorMark Thom <[email protected]>
Mon, 7 Feb 2022 04:12:54 +0000 (21:12 -0700)
committerMark Thom <[email protected]>
Mon, 7 Feb 2022 04:36:49 +0000 (21:36 -0700)
src/heap_print.rs
src/machine/machine_errors.rs
src/machine/system_calls.rs

index 0a664c6a49ccb62833cae398e3f72400e48de840..1dfba3759da614ecc22a56712a2fff658346e80e 100644 (file)
@@ -13,6 +13,7 @@ use crate::forms::*;
 use crate::heap_iter::*;
 use crate::machine::heap::*;
 use crate::machine::machine_indices::*;
+use crate::machine::machine_state::pstr_loc_and_offset;
 use crate::machine::partial_string::*;
 use crate::machine::streams::*;
 use crate::types::*;
@@ -203,6 +204,7 @@ impl NumberFocus {
 enum TokenOrRedirect {
     Atom(Atom),
     BarAsOp,
+    Char(char),
     Op(Atom, OpDesc),
     NumberedVar(String),
     CompositeRedirect(usize, DirectedOp),
@@ -1130,20 +1132,23 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
         let end_h = heap_pstr_iter.focus();
         let end_cell = heap_pstr_iter.focus;
 
-        self.remove_list_children(focus);
-
         if self.check_max_depth(&mut max_depth) {
+            self.remove_list_children(focus);
             self.state_stack.push(TokenOrRedirect::Atom(atom!("...")));
             return;
         }
 
-        let at_cdr = self.at_cdr(",");
+        let at_cdr = self.outputter.ends_with("|");
 
         if !at_cdr && !self.ignore_ops && end_cell.is_string_terminator(&self.iter.heap) {
+            self.remove_list_children(focus);
             return self.print_proper_string(focus, max_depth);
         }
 
         if self.ignore_ops {
+            self.at_cdr(",");
+            self.remove_list_children(focus);
+
             if !self.print_string_as_functor(focus, max_depth) {
                 if end_cell == empty_list_as_cell!() {
                     append_str!(self, "[]");
@@ -1153,49 +1158,52 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
                 }
             }
         } else {
-            let switch = if !at_cdr {
-                push_char!(self, '[');
-                true
-            } else {
-                false
-            };
+            let value  = heap_bound_store(
+                self.iter.heap,
+                heap_bound_deref(self.iter.heap, self.iter.heap[focus]),
+            );
 
-            let heap_pstr_iter = HeapPStrIter::new(self.iter.heap, focus);
+            read_heap_cell!(value,
+                (HeapCellValueTag::Lis) => {
+                    return self.push_list(max_depth);
+                }
+                _ => {
+                    let switch = Rc::new(Cell::new((!at_cdr, 0)));
+                    self.state_stack.push(TokenOrRedirect::CloseList(switch.clone()));
 
-            let mut iter = heap_pstr_iter.chars();
-            let mut char_count = 0;
+                    let (h, offset) = pstr_loc_and_offset(self.iter.heap, focus);
+                    let pstr = cell_as_string!(self.iter.heap[h]);
 
-            while let Some(c) = iter.next() {
-                print_char!(self, self.quoted, c);
-                push_char!(self, ',');
+                    let pstr = pstr.as_str_from(offset.get_num() as usize);
 
-                char_count += 1;
+                    if max_depth > 0 && pstr.chars().count() + 1 >= max_depth {
+                        if value.get_tag() != HeapCellValueTag::CStr {
+                            self.iter.pop_stack();
+                        }
 
-                if max_depth > 0 && max_depth <= char_count {
-                    break;
-                }
-            }
+                        self.state_stack.push(TokenOrRedirect::Atom(atom!("...")));
+                        self.state_stack.push(TokenOrRedirect::HeadTailSeparator);
+                    } else if end_cell != empty_list_as_cell!() {
+                        self.state_stack.push(TokenOrRedirect::FunctorRedirect(max_depth));
+                        self.state_stack.push(TokenOrRedirect::HeadTailSeparator);
+                    }
 
-            self.state_stack.push(TokenOrRedirect::CloseList(Rc::new(Cell::new((switch, 0)))));
+                    for (char_count, c) in pstr.chars().rev().enumerate() {
+                        if max_depth > 0 && char_count + 1 >= max_depth {
+                            break;
+                        }
 
-            if self.max_depth > 0 && iter.next().is_some() {
-                self.state_stack.push(TokenOrRedirect::Atom(atom!("...")));
-                self.state_stack.push(TokenOrRedirect::HeadTailSeparator);
-            } else {
-                if iter.cycle_detected() {
-                    self.iter.heap[end_h].set_forwarding_bit(true);
-                }
+                        self.state_stack.push(TokenOrRedirect::Char(c));
+                        self.state_stack.push(TokenOrRedirect::Comma);
+                    }
 
-                if end_cell != empty_list_as_cell!() {
-                    self.state_stack.push(TokenOrRedirect::FunctorRedirect(max_depth));
-                    self.state_stack.push(TokenOrRedirect::HeadTailSeparator);
-                    self.iter.push_stack(end_h);
-                }
-            }
+                    if let Some(TokenOrRedirect::Comma) = self.state_stack.last() {
+                        self.state_stack.pop();
+                    }
 
-            if self.outputter.ends_with(",") {
-                self.outputter.truncate(self.outputter.len() - ','.len_utf8());
-            }
+                    self.state_stack.push(TokenOrRedirect::OpenList(switch));
+                }
+            );
         }
     }
 
@@ -1507,6 +1515,7 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
                 match loc_data {
                     TokenOrRedirect::Atom(atom) => self.print_atom(atom),
                     TokenOrRedirect::BarAsOp => append_str!(self, " | "),
+                    TokenOrRedirect::Char(c) => print_char!(self, self.quoted, c),
                     TokenOrRedirect::Op(atom, _) => self.print_op(atom.as_str()),
                     TokenOrRedirect::NumberedVar(num_var) => append_str!(self, &num_var),
                     TokenOrRedirect::CompositeRedirect(max_depth, op) => {
index cd6cb9827186defbb183c09924924e82b29e775c..718a57b43537578724c8974e5f2eb39e1ac2eba8 100644 (file)
@@ -5,6 +5,7 @@ use crate::forms::*;
 use crate::machine::heap::*;
 use crate::machine::loader::CompilationTarget;
 use crate::machine::machine_state::*;
+use crate::machine::system_calls::BrentAlgState;
 use crate::types::*;
 
 pub type MachineStub = Vec<HeapCellValue>;
@@ -783,10 +784,10 @@ impl MachineState {
     pub(super) fn check_sort_errors(&mut self) -> CallResult {
         let stub_gen = || functor_stub(atom!("sort"), 2);
 
-        let list = self.registers[1];
+        let list = self.store(self.deref(self.registers[1]));
         let sorted = self.registers[2];
 
-        match self.detect_cycles(list) {
+        match BrentAlgState::detect_cycles(&self.heap, list) {
             CycleSearchResult::PartialList(..) => {
                 let err = self.instantiation_error();
                 return Err(self.error_form(err, stub_gen()))
@@ -798,7 +799,7 @@ impl MachineState {
             _ => {}
         };
 
-        match self.detect_cycles(sorted) {
+        match BrentAlgState::detect_cycles(&self.heap, sorted) {
             CycleSearchResult::NotList if !sorted.is_var() => {
                 let err = self.type_error(ValidType::List, sorted);
                 Err(self.error_form(err, stub_gen()))
@@ -810,7 +811,7 @@ impl MachineState {
     fn check_for_list_pairs(&mut self, mut list: HeapCellValue) -> CallResult {
         let stub_gen = || functor_stub(atom!("keysort"), 2);
 
-        match self.detect_cycles(list) {
+        match BrentAlgState::detect_cycles(&self.heap, list) {
             CycleSearchResult::NotList if !list.is_var() => {
                 let err = self.type_error(ValidType::List, list);
                 Err(self.error_form(err, stub_gen()))
@@ -872,7 +873,7 @@ impl MachineState {
         let pairs = self.store(self.deref(self[temp_v!(1)]));
         let sorted = self.store(self.deref(self[temp_v!(2)]));
 
-        match self.detect_cycles(pairs) {
+        match BrentAlgState::detect_cycles(&self.heap, pairs) {
             CycleSearchResult::PartialList(..) => {
                 let err = self.instantiation_error();
                 Err(self.error_form(err, stub_gen()))
index f2f8edd9814011874897a4591ce8feaa20c98cc3..ee4d152d7dcd6296d3b4c2181d51cc9a3ae54ec1 100644 (file)
@@ -209,29 +209,27 @@ impl BrentAlgState {
             }
         )
     }
-}
 
-impl MachineState {
     #[inline(always)]
-    pub fn brents_alg_step(&self, brent_st: &mut BrentAlgState) -> Option<CycleSearchResult> {
+    fn cycle_step(&mut self, heap: &[HeapCellValue]) -> Option<CycleSearchResult> {
         loop {
-            let store_v = self.heap[brent_st.hare];
+            let value = heap[self.hare];
 
-            read_heap_cell!(store_v,
+            read_heap_cell!(value,
                 (HeapCellValueTag::PStrLoc, h) => {
-                    return brent_st.add_pstr_chars_and_step(&self.heap, h);
+                    return self.add_pstr_chars_and_step(&heap, h);
                 }
                 (HeapCellValueTag::CStr | HeapCellValueTag::PStrOffset) => {
-                    return brent_st.add_pstr_chars_and_step(&self.heap, brent_st.hare);
+                    return self.add_pstr_chars_and_step(&heap, self.hare);
                 }
                 (HeapCellValueTag::Lis, h) => {
-                    return brent_st.step(h+1);
+                    return self.step(h+1);
                 }
                 (HeapCellValueTag::Str, s) => {
-                    let (name, arity) = cell_as_atom_cell!(self.heap[s]).get_name_and_arity();
+                    let (name, arity) = cell_as_atom_cell!(heap[s]).get_name_and_arity();
 
                     return if name == atom!(".") && arity == 2 {
-                        brent_st.step(s+2)
+                        self.step(s+2)
                     } else {
                         Some(CycleSearchResult::NotList)
                     };
@@ -240,18 +238,18 @@ impl MachineState {
                     debug_assert!(arity == 0);
 
                     return if name == atom!("[]") {
-                        Some(CycleSearchResult::ProperList(brent_st.num_steps()))
+                        Some(CycleSearchResult::ProperList(self.num_steps()))
                     } else {
                         Some(CycleSearchResult::NotList)
                     };
                 }
                 (HeapCellValueTag::AttrVar | HeapCellValueTag::Var, h) => {
-                    if brent_st.hare == h {
-                        let r = store_v.as_var().unwrap();
-                        return Some(CycleSearchResult::PartialList(brent_st.num_steps(), r));
+                    if self.hare == h {
+                        let r = value.as_var().unwrap();
+                        return Some(CycleSearchResult::PartialList(self.num_steps(), r));
                     }
 
-                    brent_st.hare = h;
+                    self.hare = h;
                 }
                 _ => {
                     return Some(CycleSearchResult::NotList);
@@ -260,25 +258,24 @@ impl MachineState {
         }
     }
 
-    pub fn detect_cycles(&self, value: HeapCellValue) -> CycleSearchResult {
-        let store_v = self.store(self.deref(value));
+    pub fn detect_cycles(heap: &[HeapCellValue], value: HeapCellValue) -> CycleSearchResult {
         let mut pstr_chars = 0;
 
-        let hare = read_heap_cell!(store_v,
+        let hare = read_heap_cell!(value,
             (HeapCellValueTag::Lis, offset) => {
                 offset+1
             }
             (HeapCellValueTag::PStrLoc, h) => {
-                let (h_offset, n) = pstr_loc_and_offset(&self.heap, h);
+                let (h_offset, n) = pstr_loc_and_offset(&heap, h);
                 let n = n.get_num() as usize;
-                let pstr = cell_as_string!(self.heap[h_offset]);
+                let pstr = cell_as_string!(heap[h_offset]);
 
                 pstr_chars = pstr.as_str_from(n).chars().count() - 1;
 
-                if self.heap[h].get_tag() == HeapCellValueTag::PStrOffset {
-                    debug_assert!(self.heap[h].get_tag() == HeapCellValueTag::PStrOffset);
+                if heap[h].get_tag() == HeapCellValueTag::PStrOffset {
+                    debug_assert!(heap[h].get_tag() == HeapCellValueTag::PStrOffset);
 
-                    if self.heap[h_offset].get_tag() == HeapCellValueTag::CStr {
+                    if heap[h_offset].get_tag() == HeapCellValueTag::CStr {
                         return CycleSearchResult::ProperList(pstr_chars + 1);
                     }
                 }
@@ -293,7 +290,7 @@ impl MachineState {
                 return CycleSearchResult::ProperList(cstr.as_str_from(0).chars().count());
             }
             (HeapCellValueTag::Str, s) => {
-                let (name, arity) = cell_as_atom_cell!(self.heap[s])
+                let (name, arity) = cell_as_atom_cell!(heap[s])
                     .get_name_and_arity();
 
                 if name == atom!("[]") && arity == 0 {
@@ -312,7 +309,7 @@ impl MachineState {
                 };
             }
             (HeapCellValueTag::AttrVar | HeapCellValueTag::StackVar | HeapCellValueTag::Var) => {
-                return CycleSearchResult::PartialList(0, store_v.as_var().unwrap());
+                return CycleSearchResult::PartialList(0, value.as_var().unwrap());
             }
             _ => {
                 return CycleSearchResult::NotList;
@@ -325,17 +322,20 @@ impl MachineState {
         brent_st.pstr_chars = pstr_chars;
 
         loop {
-            if let Some(result) = self.brents_alg_step(&mut brent_st) {
+            if let Some(result) = brent_st.cycle_step(heap) {
                 return result;
             }
         }
     }
 
-    pub fn detect_cycles_with_max(&self, max_steps: usize, value: HeapCellValue) -> CycleSearchResult {
-        let store_v = self.store(self.deref(value));
+    pub fn detect_cycles_with_max(
+        heap: &[HeapCellValue],
+        max_steps: usize,
+        value: HeapCellValue,
+    ) -> CycleSearchResult {
         let mut pstr_chars = 0;
 
-        let hare = read_heap_cell!(store_v,
+        let hare = read_heap_cell!(value,
             (HeapCellValueTag::Lis, offset) => {
                 if max_steps > 0 {
                     offset+1
@@ -344,16 +344,16 @@ impl MachineState {
                 }
             }
             (HeapCellValueTag::PStrLoc, h) => {
-                let (h_offset, n) = pstr_loc_and_offset(&self.heap, h);
+                let (h_offset, n) = pstr_loc_and_offset(&heap, h);
                 let n = n.get_num() as usize;
-                let pstr = cell_as_string!(self.heap[h_offset]);
+                let pstr = cell_as_string!(heap[h_offset]);
 
                 pstr_chars = pstr.as_str_from(n).chars().count() - 1;
 
-                if self.heap[h].get_tag() == HeapCellValueTag::PStrOffset {
-                    debug_assert!(self.heap[h].get_tag() == HeapCellValueTag::PStrOffset);
+                if heap[h].get_tag() == HeapCellValueTag::PStrOffset {
+                    debug_assert!(heap[h].get_tag() == HeapCellValueTag::PStrOffset);
 
-                    if self.heap[h_offset].get_tag() == HeapCellValueTag::CStr {
+                    if heap[h_offset].get_tag() == HeapCellValueTag::CStr {
                         return if pstr_chars + 1 <= max_steps {
                             CycleSearchResult::ProperList(pstr_chars + 1)
                         } else {
@@ -386,7 +386,7 @@ impl MachineState {
                 };
             }
             (HeapCellValueTag::Str, s) => {
-                let (name, arity) = cell_as_atom_cell!(self.heap[s]).get_name_and_arity();
+                let (name, arity) = cell_as_atom_cell!(heap[s]).get_name_and_arity();
 
                 if name == atom!("[]") && arity == 0 {
                     return CycleSearchResult::EmptyList;
@@ -408,7 +408,7 @@ impl MachineState {
                 };
             }
             (HeapCellValueTag::AttrVar | HeapCellValueTag::StackVar | HeapCellValueTag::Var) => {
-                return CycleSearchResult::PartialList(0, store_v.as_var().unwrap());
+                return CycleSearchResult::PartialList(0, value.as_var().unwrap());
             }
             _ => {
                 return CycleSearchResult::NotList;
@@ -422,15 +422,17 @@ impl MachineState {
 
         loop {
             if brent_st.num_steps() >= max_steps {
-                return brent_st.to_result(&self.heap);
+                return brent_st.to_result(&heap);
             }
 
-            if let Some(result) = self.brents_alg_step(&mut brent_st) {
+            if let Some(result) = brent_st.cycle_step(heap) {
                 return result;
             }
         }
     }
+}
 
+impl MachineState {
     fn skip_max_list_cycle(&mut self, lam: usize) {
         fn step(heap: &[HeapCellValue], mut value: HeapCellValue) -> usize {
             loop {
@@ -479,10 +481,10 @@ impl MachineState {
 
         let mut brent_st = BrentAlgState::new(h);
 
-        self.brents_alg_step(&mut brent_st);
+        brent_st.cycle_step(&self.heap);
 
         while prev_hare != brent_st.hare {
-            self.brents_alg_step(&mut brent_st);
+            brent_st.cycle_step(&self.heap);
         }
 
         self.heap.pop();
@@ -507,9 +509,16 @@ impl MachineState {
 
     fn skip_max_list_result(&mut self, max_steps: i64) {
         let search_result = if max_steps == -1 {
-            self.detect_cycles(self.registers[3])
+            BrentAlgState::detect_cycles(
+                &self.heap,
+                self.store(self.deref(self.registers[3])),
+            )
         } else {
-            self.detect_cycles_with_max(max_steps as usize, self.registers[3])
+            BrentAlgState::detect_cycles_with_max(
+                &self.heap,
+                max_steps as usize,
+                self.store(self.deref(self.registers[3])),
+            )
         };
 
         match search_result {