fix various partial string bugs (copying using them in arg/3)
This commit is contained in:
@@ -41,6 +41,8 @@
|
|||||||
trie_get_all_values/2 % +Trie, -Value
|
trie_get_all_values/2 % +Trie, -Value
|
||||||
]).
|
]).
|
||||||
|
|
||||||
|
:- use_module(library(format)).
|
||||||
|
|
||||||
:- use_module(library(assoc)).
|
:- use_module(library(assoc)).
|
||||||
:- use_module(library(atts)).
|
:- use_module(library(atts)).
|
||||||
:- use_module(library(lists)).
|
:- use_module(library(lists)).
|
||||||
|
|||||||
@@ -107,13 +107,14 @@ impl<T: CopierTarget> CopyTermState<T> {
|
|||||||
fn copy_partial_string(&mut self, scan_tag: HeapCellValueTag, pstr_loc: usize) {
|
fn copy_partial_string(&mut self, scan_tag: HeapCellValueTag, pstr_loc: usize) {
|
||||||
read_heap_cell!(self.target[pstr_loc],
|
read_heap_cell!(self.target[pstr_loc],
|
||||||
(HeapCellValueTag::PStrLoc, h) => {
|
(HeapCellValueTag::PStrLoc, h) => {
|
||||||
if h >= self.old_h {
|
debug_assert!(h >= self.old_h);
|
||||||
|
|
||||||
*self.value_at_scan() = match scan_tag {
|
*self.value_at_scan() = match scan_tag {
|
||||||
HeapCellValueTag::PStrLoc => {
|
HeapCellValueTag::PStrLoc => {
|
||||||
pstr_loc_as_cell!(h)
|
pstr_loc_as_cell!(h)
|
||||||
}
|
}
|
||||||
tag => {
|
tag => {
|
||||||
debug_assert!(tag == HeapCellValueTag::PStrOffset);
|
debug_assert_eq!(tag, HeapCellValueTag::PStrOffset);
|
||||||
pstr_offset_as_cell!(h)
|
pstr_offset_as_cell!(h)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -121,22 +122,48 @@ impl<T: CopierTarget> CopyTermState<T> {
|
|||||||
self.scan += 1;
|
self.scan += 1;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
(HeapCellValueTag::Var, h) => {
|
||||||
|
debug_assert!(h >= self.old_h);
|
||||||
|
debug_assert_eq!(scan_tag, HeapCellValueTag::PStrOffset);
|
||||||
|
|
||||||
|
*self.value_at_scan() = pstr_offset_as_cell!(h);
|
||||||
|
self.scan += 1;
|
||||||
|
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
);
|
);
|
||||||
|
|
||||||
let threshold = self.target.threshold();
|
let threshold = self.target.threshold();
|
||||||
|
|
||||||
*self.value_at_scan() = pstr_loc_as_cell!(threshold);
|
let replacement = read_heap_cell!(self.target[pstr_loc],
|
||||||
self.scan += 1;
|
(HeapCellValueTag::CStr) => {
|
||||||
|
debug_assert_eq!(scan_tag, HeapCellValueTag::PStrOffset);
|
||||||
|
|
||||||
|
*self.value_at_scan() = pstr_offset_as_cell!(threshold);
|
||||||
self.target.push(self.target[pstr_loc]);
|
self.target.push(self.target[pstr_loc]);
|
||||||
|
|
||||||
let replacement = pstr_loc_as_cell!(threshold);
|
heap_loc_as_cell!(threshold)
|
||||||
let trail_item = mem::replace(&mut self.target[pstr_loc], replacement);
|
}
|
||||||
|
_ => {
|
||||||
|
*self.value_at_scan() = if scan_tag == HeapCellValueTag::PStrLoc {
|
||||||
|
pstr_loc_as_cell!(threshold)
|
||||||
|
} else {
|
||||||
|
debug_assert_eq!(scan_tag, HeapCellValueTag::PStrOffset);
|
||||||
|
pstr_offset_as_cell!(threshold)
|
||||||
|
};
|
||||||
|
|
||||||
self.trail.push((Ref::heap_cell(pstr_loc), trail_item));
|
self.target.push(self.target[pstr_loc]);
|
||||||
self.target.push(self.target[pstr_loc + 1]);
|
self.target.push(self.target[pstr_loc + 1]);
|
||||||
|
|
||||||
|
pstr_loc_as_cell!(threshold)
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
self.scan += 1;
|
||||||
|
|
||||||
|
let trail_item = mem::replace(&mut self.target[pstr_loc], replacement);
|
||||||
|
self.trail.push((Ref::heap_cell(pstr_loc), trail_item));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn reinstantiate_var(&mut self, addr: HeapCellValue, frontier: usize) {
|
fn reinstantiate_var(&mut self, addr: HeapCellValue, frontier: usize) {
|
||||||
@@ -185,7 +212,7 @@ impl<T: CopierTarget> CopyTermState<T> {
|
|||||||
read_heap_cell!(ra,
|
read_heap_cell!(ra,
|
||||||
(HeapCellValueTag::AttrVar | HeapCellValueTag::Var, h) => {
|
(HeapCellValueTag::AttrVar | HeapCellValueTag::Var, h) => {
|
||||||
if h >= self.old_h {
|
if h >= self.old_h {
|
||||||
*self.value_at_scan() = rd;
|
*self.value_at_scan() = ra;
|
||||||
self.scan += 1;
|
self.scan += 1;
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -3046,11 +3046,26 @@ impl MachineState {
|
|||||||
} else {
|
} else {
|
||||||
let offset = (offset + c.len_utf8()) as i64;
|
let offset = (offset + c.len_utf8()) as i64;
|
||||||
let h_len = self.heap.len();
|
let h_len = self.heap.len();
|
||||||
|
let pstr_atom: Atom = pstr.into();
|
||||||
|
|
||||||
self.heap.push(pstr_offset_as_cell!(h_len));
|
if pstr_atom.len() > offset as usize {
|
||||||
|
self.heap.push(pstr_offset_as_cell!(h));
|
||||||
self.heap.push(fixnum_as_cell!(Fixnum::build_with(offset)));
|
self.heap.push(fixnum_as_cell!(Fixnum::build_with(offset)));
|
||||||
|
|
||||||
unify_fn!(self, pstr_loc_as_cell!(h_len), a3);
|
unify_fn!(self, pstr_loc_as_cell!(h_len), a3);
|
||||||
|
} else {
|
||||||
|
match self.heap[h].get_tag() {
|
||||||
|
HeapCellValueTag::CStr => {
|
||||||
|
self.unify_atom(atom!("[]"), self.store(self.deref(a3)));
|
||||||
|
}
|
||||||
|
HeapCellValueTag::PStr => {
|
||||||
|
unify_fn!(self, self.heap[h+1], a3);
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
unreachable!();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
@@ -3059,6 +3074,32 @@ impl MachineState {
|
|||||||
self.fail = true;
|
self.fail = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
(HeapCellValueTag::CStr, cstr_atom) => {
|
||||||
|
let cstr = PartialString::from(cstr_atom);
|
||||||
|
|
||||||
|
if let Some(c) = cstr.as_str_from(0).chars().next() {
|
||||||
|
if n == 1 {
|
||||||
|
self.unify_char(c, self.store(self.deref(self.registers[3])));
|
||||||
|
} else if n == 2 {
|
||||||
|
let offset = c.len_utf8() as i64;
|
||||||
|
let h_len = self.heap.len();
|
||||||
|
|
||||||
|
if cstr_atom.len() > offset as usize {
|
||||||
|
self.heap.push(atom_as_cstr_cell!(cstr_atom));
|
||||||
|
self.heap.push(pstr_offset_as_cell!(h_len));
|
||||||
|
self.heap.push(fixnum_as_cell!(Fixnum::build_with(offset)));
|
||||||
|
|
||||||
|
unify_fn!(self, pstr_loc_as_cell!(h_len+1), self.registers[3]);
|
||||||
|
} else {
|
||||||
|
self.unify_atom(atom!("[]"), self.store(self.deref(self.registers[3])));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
self.fail = true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
}
|
||||||
_ => {
|
_ => {
|
||||||
// 8.5.2.3 d)
|
// 8.5.2.3 d)
|
||||||
let err = self.type_error(ValidType::Compound, term);
|
let err = self.type_error(ValidType::Compound, term);
|
||||||
@@ -3361,7 +3402,7 @@ impl MachineState {
|
|||||||
let (name, arity) = cell_as_atom_cell!(self.heap[s]).get_name_and_arity();
|
let (name, arity) = cell_as_atom_cell!(self.heap[s]).get_name_and_arity();
|
||||||
self.try_functor_compound_case(name, arity);
|
self.try_functor_compound_case(name, arity);
|
||||||
}
|
}
|
||||||
(HeapCellValueTag::Lis | HeapCellValueTag::PStrOffset) => {
|
(HeapCellValueTag::Lis | HeapCellValueTag::PStrLoc | HeapCellValueTag::CStr) => {
|
||||||
self.try_functor_compound_case(atom!("."), 2);
|
self.try_functor_compound_case(atom!("."), 2);
|
||||||
}
|
}
|
||||||
(HeapCellValueTag::Var | HeapCellValueTag::AttrVar | HeapCellValueTag::StackVar) => {
|
(HeapCellValueTag::Var | HeapCellValueTag::AttrVar | HeapCellValueTag::StackVar) => {
|
||||||
|
|||||||
@@ -729,6 +729,7 @@ impl Sub<i64> for HeapCellValue {
|
|||||||
tag @ HeapCellValueTag::Str |
|
tag @ HeapCellValueTag::Str |
|
||||||
tag @ HeapCellValueTag::Lis |
|
tag @ HeapCellValueTag::Lis |
|
||||||
tag @ HeapCellValueTag::PStrOffset |
|
tag @ HeapCellValueTag::PStrOffset |
|
||||||
|
tag @ HeapCellValueTag::PStrLoc |
|
||||||
tag @ HeapCellValueTag::Var |
|
tag @ HeapCellValueTag::Var |
|
||||||
tag @ HeapCellValueTag::AttrVar => {
|
tag @ HeapCellValueTag::AttrVar => {
|
||||||
HeapCellValue::build_with(tag, (self.get_value() + rhs.abs() as usize) as u64)
|
HeapCellValue::build_with(tag, (self.get_value() + rhs.abs() as usize) as u64)
|
||||||
|
|||||||
Reference in New Issue
Block a user