From: Mark Thom Date: Wed, 1 Dec 2021 05:35:38 +0000 (-0700) Subject: fix various partial string bugs (copying using them in arg/3) X-Git-Tag: v0.9.0^2~111 X-Git-Url: https://git.sagredo.dev/?a=commitdiff_plain;h=fb4e627e6281bae6176b61fef27e021decbdb92a;p=scryer-prolog.git fix various partial string bugs (copying using them in arg/3) --- diff --git a/src/lib/tabling/trie.pl b/src/lib/tabling/trie.pl index cd855b92..2460f70f 100644 --- a/src/lib/tabling/trie.pl +++ b/src/lib/tabling/trie.pl @@ -41,6 +41,8 @@ trie_get_all_values/2 % +Trie, -Value ]). +:- use_module(library(format)). + :- use_module(library(assoc)). :- use_module(library(atts)). :- use_module(library(lists)). diff --git a/src/machine/copier.rs b/src/machine/copier.rs index f5417e53..fd016fd6 100644 --- a/src/machine/copier.rs +++ b/src/machine/copier.rs @@ -107,36 +107,63 @@ impl CopyTermState { fn copy_partial_string(&mut self, scan_tag: HeapCellValueTag, pstr_loc: usize) { read_heap_cell!(self.target[pstr_loc], (HeapCellValueTag::PStrLoc, h) => { - if h >= self.old_h { - *self.value_at_scan() = match scan_tag { - HeapCellValueTag::PStrLoc => { - pstr_loc_as_cell!(h) - } - tag => { - debug_assert!(tag == HeapCellValueTag::PStrOffset); - pstr_offset_as_cell!(h) - } - }; + debug_assert!(h >= self.old_h); - self.scan += 1; - return; - } + *self.value_at_scan() = match scan_tag { + HeapCellValueTag::PStrLoc => { + pstr_loc_as_cell!(h) + } + tag => { + debug_assert_eq!(tag, HeapCellValueTag::PStrOffset); + pstr_offset_as_cell!(h) + } + }; + + self.scan += 1; + 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(); - *self.value_at_scan() = pstr_loc_as_cell!(threshold); - self.scan += 1; + let replacement = read_heap_cell!(self.target[pstr_loc], + (HeapCellValueTag::CStr) => { + debug_assert_eq!(scan_tag, HeapCellValueTag::PStrOffset); - self.target.push(self.target[pstr_loc]); + *self.value_at_scan() = pstr_offset_as_cell!(threshold); + self.target.push(self.target[pstr_loc]); - let replacement = pstr_loc_as_cell!(threshold); - let trail_item = mem::replace(&mut self.target[pstr_loc], replacement); + heap_loc_as_cell!(threshold) + } + _ => { + *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.target.push(self.target[pstr_loc]); + 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)); - self.target.push(self.target[pstr_loc + 1]); } fn reinstantiate_var(&mut self, addr: HeapCellValue, frontier: usize) { @@ -185,7 +212,7 @@ impl CopyTermState { read_heap_cell!(ra, (HeapCellValueTag::AttrVar | HeapCellValueTag::Var, h) => { if h >= self.old_h { - *self.value_at_scan() = rd; + *self.value_at_scan() = ra; self.scan += 1; return; diff --git a/src/machine/machine_state_impl.rs b/src/machine/machine_state_impl.rs index b0416b1d..dbf44bed 100644 --- a/src/machine/machine_state_impl.rs +++ b/src/machine/machine_state_impl.rs @@ -3046,11 +3046,26 @@ impl MachineState { } else { let offset = (offset + c.len_utf8()) as i64; let h_len = self.heap.len(); + let pstr_atom: Atom = pstr.into(); - self.heap.push(pstr_offset_as_cell!(h_len)); - self.heap.push(fixnum_as_cell!(Fixnum::build_with(offset))); + 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))); - 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 { unreachable!() @@ -3059,6 +3074,32 @@ impl MachineState { 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) 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(); self.try_functor_compound_case(name, arity); } - (HeapCellValueTag::Lis | HeapCellValueTag::PStrOffset) => { + (HeapCellValueTag::Lis | HeapCellValueTag::PStrLoc | HeapCellValueTag::CStr) => { self.try_functor_compound_case(atom!("."), 2); } (HeapCellValueTag::Var | HeapCellValueTag::AttrVar | HeapCellValueTag::StackVar) => { diff --git a/src/types.rs b/src/types.rs index b0339a1a..16805981 100644 --- a/src/types.rs +++ b/src/types.rs @@ -729,6 +729,7 @@ impl Sub for HeapCellValue { tag @ HeapCellValueTag::Str | tag @ HeapCellValueTag::Lis | tag @ HeapCellValueTag::PStrOffset | + tag @ HeapCellValueTag::PStrLoc | tag @ HeapCellValueTag::Var | tag @ HeapCellValueTag::AttrVar => { HeapCellValue::build_with(tag, (self.get_value() + rhs.abs() as usize) as u64)