]> Repositorios git - scryer-prolog.git/commitdiff
fix various partial string bugs (copying using them in arg/3)
authorMark Thom <[email protected]>
Wed, 1 Dec 2021 05:35:38 +0000 (22:35 -0700)
committerMark Thom <[email protected]>
Fri, 7 Jan 2022 04:44:41 +0000 (21:44 -0700)
src/lib/tabling/trie.pl
src/machine/copier.rs
src/machine/machine_state_impl.rs
src/types.rs

index cd855b9243badd605e89a0f212970bdcdb83ff2e..2460f70f25e5c4b50d505a995f9e4be6b411ffaf 100644 (file)
@@ -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)).
index f5417e5320ffe50a383fe91e4c804c951f44a75e..fd016fd6b8691ae9e5817205a95786c7693e4c9f 100644 (file)
@@ -107,36 +107,63 @@ impl<T: CopierTarget> CopyTermState<T> {
     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<T: CopierTarget> CopyTermState<T> {
         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;
index b0416b1d86ceac7418560555409d10638f800a25..dbf44bed631bcc86514d12c7e3a2d8585daac914 100644 (file)
@@ -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) => {
index b0339a1a59dcd4dba13f948533cf1c1ed72f4d2e..16805981d6a12fe54eb8dbaeabb6e5b01c94b36e 100644 (file)
@@ -729,6 +729,7 @@ impl Sub<i64> 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)