properly account for partial string offsets in '$skip_max_list' (#1827)
This commit is contained in:
@@ -799,7 +799,7 @@ pub enum CycleSearchResult {
|
|||||||
NotList(usize, HeapCellValue), // the list length until the second argument in the heap
|
NotList(usize, HeapCellValue), // the list length until the second argument in the heap
|
||||||
PartialList(usize, Ref), // the list length (up to max), and an offset into the heap.
|
PartialList(usize, Ref), // the list length (up to max), and an offset into the heap.
|
||||||
ProperList(usize), // the list length.
|
ProperList(usize), // the list length.
|
||||||
PStrLocation(usize, usize), // list length (up to max), the heap address of the PStrOffset
|
PStrLocation(usize, usize, usize), // list length (up to max), the heap address of the PStr, the offset
|
||||||
UntouchedList(usize, usize), // list length (up to max), the address of an uniterated Addr::Lis(address).
|
UntouchedList(usize, usize), // list length (up to max), the address of an uniterated Addr::Lis(address).
|
||||||
UntouchedCStr(Atom, usize),
|
UntouchedCStr(Atom, usize),
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -120,6 +120,7 @@ pub struct BrentAlgState {
|
|||||||
pub power: usize,
|
pub power: usize,
|
||||||
pub lam: usize,
|
pub lam: usize,
|
||||||
pub pstr_chars: usize,
|
pub pstr_chars: usize,
|
||||||
|
max_steps: i64,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BrentAlgState {
|
impl BrentAlgState {
|
||||||
@@ -130,6 +131,7 @@ impl BrentAlgState {
|
|||||||
power: 1,
|
power: 1,
|
||||||
lam: 0,
|
lam: 0,
|
||||||
pstr_chars: 0,
|
pstr_chars: 0,
|
||||||
|
max_steps: -1,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -161,72 +163,95 @@ impl BrentAlgState {
|
|||||||
return self.lam + self.pstr_chars + self.power - 1;
|
return self.lam + self.pstr_chars + self.power - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
pub fn exhausted_max_steps(&self) -> bool {
|
||||||
|
self.max_steps > -1 && self.num_steps() as i64 >= self.max_steps
|
||||||
|
}
|
||||||
|
|
||||||
pub fn to_result(mut self, heap: &[HeapCellValue]) -> CycleSearchResult {
|
pub fn to_result(mut self, heap: &[HeapCellValue]) -> CycleSearchResult {
|
||||||
|
/*
|
||||||
if let Some(var) = heap[self.hare].as_var() {
|
if let Some(var) = heap[self.hare].as_var() {
|
||||||
return CycleSearchResult::PartialList(self.num_steps(), var);
|
return CycleSearchResult::PartialList(self.num_steps(), var);
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
read_heap_cell!(heap[self.hare],
|
loop {
|
||||||
(HeapCellValueTag::PStrOffset) => {
|
read_heap_cell!(heap[self.hare],
|
||||||
let n = cell_as_fixnum!(heap[self.hare+1]).get_num() as usize;
|
(HeapCellValueTag::PStrOffset) => {
|
||||||
|
let (pstr_loc, offset) = pstr_loc_and_offset(heap, self.hare);
|
||||||
|
let offset = offset.get_num() as usize;
|
||||||
|
|
||||||
let pstr = cell_as_string!(heap[self.hare]);
|
let pstr = cell_as_string!(heap[self.hare]);
|
||||||
self.pstr_chars += pstr.as_str_from(n).chars().count();
|
self.pstr_chars += pstr.as_str_from(offset).chars().count();
|
||||||
|
|
||||||
return CycleSearchResult::PStrLocation(self.num_steps(), n);
|
return CycleSearchResult::PStrLocation(self.num_steps(), pstr_loc, offset);
|
||||||
}
|
}
|
||||||
(HeapCellValueTag::Atom, (name, arity)) => {
|
(HeapCellValueTag::PStrLoc, l) => {
|
||||||
return if name == atom!("[]") && arity == 0 {
|
let (_pstr_loc, offset) = pstr_loc_and_offset(heap, l);
|
||||||
CycleSearchResult::ProperList(self.num_steps())
|
let offset = offset.get_num() as usize;
|
||||||
} else {
|
return CycleSearchResult::PStrLocation(self.num_steps(), l, offset);
|
||||||
CycleSearchResult::NotList(self.num_steps(), heap[self.hare])
|
}
|
||||||
};
|
(HeapCellValueTag::Atom, (name, arity)) => {
|
||||||
}
|
return if name == atom!("[]") && arity == 0 {
|
||||||
(HeapCellValueTag::Str, s) => {
|
CycleSearchResult::ProperList(self.num_steps())
|
||||||
let (name, arity) = cell_as_atom_cell!(heap[s])
|
} else {
|
||||||
.get_name_and_arity();
|
CycleSearchResult::NotList(self.num_steps(), heap[self.hare])
|
||||||
|
};
|
||||||
|
}
|
||||||
|
(HeapCellValueTag::Str, s) => {
|
||||||
|
let (name, arity) = cell_as_atom_cell!(heap[s])
|
||||||
|
.get_name_and_arity();
|
||||||
|
|
||||||
return if name == atom!("[]") && arity == 0 {
|
return if name == atom!("[]") && arity == 0 {
|
||||||
CycleSearchResult::ProperList(self.num_steps())
|
CycleSearchResult::ProperList(self.num_steps())
|
||||||
} else {
|
} else {
|
||||||
CycleSearchResult::NotList(self.num_steps(), heap[self.hare])
|
CycleSearchResult::NotList(self.num_steps(), heap[self.hare])
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
(HeapCellValueTag::Lis, l) => {
|
(HeapCellValueTag::Lis, l) => {
|
||||||
return CycleSearchResult::UntouchedList(self.num_steps(), l);
|
return CycleSearchResult::UntouchedList(self.num_steps(), l);
|
||||||
}
|
}
|
||||||
_ => {
|
(HeapCellValueTag::AttrVar | HeapCellValueTag::Var, h) => {
|
||||||
return CycleSearchResult::NotList(self.num_steps(), heap[self.hare]);
|
if h == self.hare {
|
||||||
}
|
let var = heap[self.hare].as_var().unwrap();
|
||||||
);
|
return CycleSearchResult::PartialList(self.num_steps(), var);
|
||||||
|
} else {
|
||||||
|
self.hare = h;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
return CycleSearchResult::NotList(self.num_steps(), heap[self.hare]);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn add_pstr_chars_and_step(&mut self, heap: &[HeapCellValue], h: usize) -> Option<CycleSearchResult> {
|
fn add_pstr_offset_chars(&mut self, heap: &[HeapCellValue], h: usize, offset: usize) -> Option<CycleSearchResult> {
|
||||||
read_heap_cell!(heap[h],
|
read_heap_cell!(heap[h],
|
||||||
(HeapCellValueTag::CStr, cstr_atom) => {
|
(HeapCellValueTag::CStr, cstr_atom) => {
|
||||||
let cstr = PartialString::from(cstr_atom);
|
let cstr = PartialString::from(cstr_atom);
|
||||||
|
let num_chars = cstr.as_str_from(offset).chars().count();
|
||||||
|
|
||||||
self.pstr_chars += cstr.as_str_from(0).chars().count();
|
if self.max_steps == -1 || self.num_steps() + num_chars < self.max_steps as usize {
|
||||||
Some(CycleSearchResult::ProperList(self.num_steps()))
|
self.pstr_chars += num_chars;
|
||||||
|
Some(CycleSearchResult::ProperList(self.num_steps()))
|
||||||
|
} else {
|
||||||
|
let offset = self.num_steps() + num_chars - self.max_steps as usize;
|
||||||
|
self.pstr_chars += offset;
|
||||||
|
Some(CycleSearchResult::PStrLocation(self.max_steps as usize, h, offset))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
(HeapCellValueTag::PStr, pstr_atom) => {
|
(HeapCellValueTag::PStr, pstr_atom) => {
|
||||||
let pstr = PartialString::from(pstr_atom);
|
let pstr = PartialString::from(pstr_atom);
|
||||||
|
let num_chars = pstr.as_str_from(offset).chars().count();
|
||||||
|
|
||||||
self.pstr_chars += pstr.as_str_from(0).chars().count() - 1;
|
if self.max_steps == -1 || self.num_steps() + num_chars < self.max_steps as usize {
|
||||||
self.step(h+1)
|
self.pstr_chars += num_chars - 1;
|
||||||
}
|
self.step(h+1)
|
||||||
(HeapCellValueTag::PStrOffset, offset) => {
|
|
||||||
let pstr = cell_as_string!(heap[offset]);
|
|
||||||
let n = cell_as_fixnum!(heap[h+1]).get_num() as usize;
|
|
||||||
|
|
||||||
self.pstr_chars += pstr.as_str_from(n).chars().count();
|
|
||||||
|
|
||||||
if let HeapCellValueTag::PStr = heap[offset].get_tag() {
|
|
||||||
self.pstr_chars -= 1;
|
|
||||||
self.step(offset+1)
|
|
||||||
} else {
|
} else {
|
||||||
debug_assert!(heap[offset].get_tag() == HeapCellValueTag::CStr);
|
let offset = self.num_steps() + num_chars - self.max_steps as usize;
|
||||||
Some(CycleSearchResult::ProperList(self.num_steps()))
|
self.pstr_chars += offset;
|
||||||
|
Some(CycleSearchResult::PStrLocation(self.max_steps as usize, h, offset))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
@@ -235,6 +260,18 @@ impl BrentAlgState {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn add_pstr_chars_and_step(&mut self, heap: &[HeapCellValue], h: usize) -> Option<CycleSearchResult> {
|
||||||
|
read_heap_cell!(heap[h],
|
||||||
|
(HeapCellValueTag::PStrOffset, l) => {
|
||||||
|
let (pstr_loc, offset) = pstr_loc_and_offset(heap, l);
|
||||||
|
self.add_pstr_offset_chars(heap, pstr_loc, offset.get_num() as usize)
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
self.add_pstr_offset_chars(heap, h, 0)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn cycle_step(&mut self, heap: &[HeapCellValue]) -> Option<CycleSearchResult> {
|
fn cycle_step(&mut self, heap: &[HeapCellValue]) -> Option<CycleSearchResult> {
|
||||||
loop {
|
loop {
|
||||||
@@ -388,7 +425,7 @@ impl BrentAlgState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if pstr_chars + 1 > max_steps {
|
if pstr_chars + 1 > max_steps {
|
||||||
return CycleSearchResult::PStrLocation(max_steps, h_offset);
|
return CycleSearchResult::PStrLocation(max_steps, h_offset, max_steps);
|
||||||
}
|
}
|
||||||
|
|
||||||
h_offset+1
|
h_offset+1
|
||||||
@@ -444,9 +481,10 @@ impl BrentAlgState {
|
|||||||
|
|
||||||
brent_st.power += 1; // advance a step.
|
brent_st.power += 1; // advance a step.
|
||||||
brent_st.pstr_chars = pstr_chars;
|
brent_st.pstr_chars = pstr_chars;
|
||||||
|
brent_st.max_steps = max_steps as i64;
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
if brent_st.num_steps() >= max_steps {
|
if brent_st.exhausted_max_steps() {
|
||||||
return brent_st.to_result(&heap);
|
return brent_st.to_result(&heap);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -638,8 +676,25 @@ impl MachineState {
|
|||||||
};
|
};
|
||||||
|
|
||||||
match search_result {
|
match search_result {
|
||||||
CycleSearchResult::PStrLocation(steps, pstr_loc) => {
|
CycleSearchResult::PStrLocation(steps, pstr_loc, offset) => {
|
||||||
self.finalize_skip_max_list(steps as i64, pstr_loc_as_cell!(pstr_loc));
|
let steps = if max_steps > - 1 {
|
||||||
|
std::cmp::min(max_steps, steps as i64)
|
||||||
|
} else {
|
||||||
|
steps as i64
|
||||||
|
};
|
||||||
|
|
||||||
|
let cell = if offset > 0 {
|
||||||
|
let h = self.heap.len();
|
||||||
|
|
||||||
|
self.heap.push(pstr_offset_as_cell!(pstr_loc));
|
||||||
|
self.heap.push(fixnum_as_cell!(Fixnum::build_with(offset as i64)));
|
||||||
|
|
||||||
|
pstr_loc_as_cell!(h)
|
||||||
|
} else {
|
||||||
|
pstr_loc_as_cell!(pstr_loc)
|
||||||
|
};
|
||||||
|
|
||||||
|
self.finalize_skip_max_list(steps, cell);
|
||||||
}
|
}
|
||||||
CycleSearchResult::UntouchedList(n, l) => {
|
CycleSearchResult::UntouchedList(n, l) => {
|
||||||
self.finalize_skip_max_list(n as i64, list_loc_as_cell!(l));
|
self.finalize_skip_max_list(n as i64, list_loc_as_cell!(l));
|
||||||
@@ -2805,7 +2860,7 @@ impl Machine {
|
|||||||
unreachable!()
|
unreachable!()
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
self.machine_st.fail = true; // This predicate fails by default.
|
self.machine_st.fail = true; // This predicate fails by default.
|
||||||
|
|
||||||
read_heap_cell!(a2,
|
read_heap_cell!(a2,
|
||||||
@@ -2868,12 +2923,12 @@ impl Machine {
|
|||||||
macro_check!(symbolic_control_char, atom!("symbolic_control"));
|
macro_check!(symbolic_control_char, atom!("symbolic_control"));
|
||||||
method_check!(is_uppercase, atom!("upper"));
|
method_check!(is_uppercase, atom!("upper"));
|
||||||
// macro_check!(variable_indicator_char, atom!("variable_indicator"));
|
// macro_check!(variable_indicator_char, atom!("variable_indicator"));
|
||||||
method_check!(is_whitespace, atom!("whitespace"));
|
method_check!(is_whitespace, atom!("whitespace"));
|
||||||
}
|
}
|
||||||
(HeapCellValueTag::Str, s) => {
|
(HeapCellValueTag::Str, s) => {
|
||||||
let (name, arity) = cell_as_atom_cell!(self.machine_st.heap[s])
|
let (name, arity) = cell_as_atom_cell!(self.machine_st.heap[s])
|
||||||
.get_name_and_arity();
|
.get_name_and_arity();
|
||||||
|
|
||||||
match (name, arity) {
|
match (name, arity) {
|
||||||
(atom!("to_upper"), 1) => {
|
(atom!("to_upper"), 1) => {
|
||||||
let reg = self.machine_st.deref(self.machine_st.heap[s+1]);
|
let reg = self.machine_st.deref(self.machine_st.heap[s+1]);
|
||||||
@@ -2888,7 +2943,7 @@ impl Machine {
|
|||||||
let lower_str = string_as_cstr_cell!(atom);
|
let lower_str = string_as_cstr_cell!(atom);
|
||||||
unify!(self.machine_st, reg, lower_str);
|
unify!(self.machine_st, reg, lower_str);
|
||||||
self.machine_st.fail = false;
|
self.machine_st.fail = false;
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
}
|
}
|
||||||
@@ -2898,9 +2953,9 @@ impl Machine {
|
|||||||
unreachable!()
|
unreachable!()
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
@@ -4238,7 +4293,7 @@ impl Machine {
|
|||||||
let query_str = request.request.uri().query().unwrap_or("");
|
let query_str = request.request.uri().query().unwrap_or("");
|
||||||
let query_atom = self.machine_st.atom_tbl.build_with(query_str);
|
let query_atom = self.machine_st.atom_tbl.build_with(query_str);
|
||||||
let query_cell = string_as_cstr_cell!(query_atom);
|
let query_cell = string_as_cstr_cell!(query_atom);
|
||||||
|
|
||||||
let hyper_req = request.request;
|
let hyper_req = request.request;
|
||||||
let buf = self.runtime.block_on(async {hyper::body::aggregate(hyper_req).await.unwrap()});
|
let buf = self.runtime.block_on(async {hyper::body::aggregate(hyper_req).await.unwrap()});
|
||||||
let reader = buf.reader();
|
let reader = buf.reader();
|
||||||
@@ -4433,7 +4488,7 @@ impl Machine {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
match self.machine_st.try_from_list(args_reg, stub_gen) {
|
match self.machine_st.try_from_list(args_reg, stub_gen) {
|
||||||
Ok(args) => {
|
Ok(args) => {
|
||||||
let args: Vec<_> = args.into_iter().map(|x| map_arg(&mut self.machine_st, x)).collect();
|
let args: Vec<_> = args.into_iter().map(|x| map_arg(&mut self.machine_st, x)).collect();
|
||||||
@@ -4482,7 +4537,7 @@ impl Machine {
|
|||||||
Value::Struct(name, struct_args) => self.build_struct(&name, struct_args),
|
Value::Struct(name, struct_args) => self.build_struct(&name, struct_args),
|
||||||
}
|
}
|
||||||
}).collect();
|
}).collect();
|
||||||
|
|
||||||
heap_loc_as_cell!(
|
heap_loc_as_cell!(
|
||||||
iter_to_heap_list(
|
iter_to_heap_list(
|
||||||
&mut self.machine_st.heap,
|
&mut self.machine_st.heap,
|
||||||
|
|||||||
Reference in New Issue
Block a user