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::*;
enum TokenOrRedirect {
Atom(Atom),
BarAsOp,
+ Char(char),
Op(Atom, OpDesc),
NumberedVar(String),
CompositeRedirect(usize, DirectedOp),
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, "[]");
}
}
} 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));
+ }
+ );
}
}
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) => {
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>;
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()))
_ => {}
};
- 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()))
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()))
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()))
}
)
}
-}
-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)
};
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);
}
}
- 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);
}
}
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 {
};
}
(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;
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
}
}
(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 {
};
}
(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;
};
}
(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;
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 {
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();
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 {