]> Repositorios git - scryer-prolog.git/commitdiff
make write_with forward return values, use it to correct partial string handling
authorMark Thom <[email protected]>
Sat, 15 Mar 2025 09:10:56 +0000 (02:10 -0700)
committerMark Thom <[email protected]>
Tue, 8 Jul 2025 05:02:27 +0000 (22:02 -0700)
src/machine/heap.rs
src/machine/machine_state.rs
src/parser/parser.rs

index d628391c661cc0971937914449a95fd0ad744607..efd4337cc4f2fc84b8a8d61425741337b11d1760 100644 (file)
@@ -183,7 +183,7 @@ impl PStrSegmentCmpResult {
 
 #[derive(Debug)]
 pub struct PStrWriteInfo {
-    pstr_loc: usize,
+    cell: HeapCellValue,
 }
 
 #[derive(Debug)]
@@ -414,29 +414,40 @@ pub struct HeapWriter<'a> {
     heap_byte_len: &'a mut usize,
 }
 
+pub(crate) struct HeapSectionWriteResult<R> {
+    pub(crate) bytes_written: usize,
+    pub(crate) result: R,
+}
+
 impl<'a> HeapWriter<'a> {
     #[allow(dead_code)]
-    pub(crate) fn write_with_error_handling<E>(
+    pub(crate) fn write_with_error_handling<R, E>(
         &mut self,
-        writer: impl FnOnce(&mut ReservedHeapSection) -> Result<(), E>,
-    ) -> Result<usize, E> {
+        writer: impl FnOnce(&mut ReservedHeapSection) -> Result<R, E>,
+    ) -> Result<HeapSectionWriteResult<R>, E> {
         let old_section_cell_len = self.section.heap_cell_len;
-        writer(&mut self.section)?;
+        let result = writer(&mut self.section)?;
         *self.heap_byte_len = heap_index!(self.section.heap_cell_len);
 
         // return the number of bytes written
-        Ok(heap_index!(
-            self.section.heap_cell_len - old_section_cell_len
-        ))
+        Ok(HeapSectionWriteResult {
+            bytes_written: heap_index!(self.section.heap_cell_len - old_section_cell_len),
+            result,
+        })
     }
 
-    pub(crate) fn write_with(&mut self, writer: impl FnOnce(&mut ReservedHeapSection)) -> usize {
+    pub(crate) fn write_with<R>(
+        &mut self,
+        writer: impl FnOnce(&mut ReservedHeapSection) -> R,
+    ) -> HeapSectionWriteResult<R> {
         let old_section_cell_len = self.section.heap_cell_len;
-        writer(&mut self.section);
+        let result = writer(&mut self.section);
         *self.heap_byte_len = heap_index!(self.section.heap_cell_len);
 
-        // return the number of bytes written
-        heap_index!(self.section.heap_cell_len - old_section_cell_len)
+        HeapSectionWriteResult {
+            bytes_written: heap_index!(self.section.heap_cell_len - old_section_cell_len),
+            result,
+        }
     }
 
     #[inline]
@@ -854,20 +865,11 @@ impl Heap {
 
     pub fn allocate_pstr(&mut self, src: &str) -> Result<Option<PStrWriteInfo>, usize> {
         let size_in_heap = Self::compute_pstr_size(src);
+        let mut writer = self.reserve(size_in_heap)?;
+        let HeapSectionWriteResult { result, .. } =
+            writer.write_with(|section| section.push_pstr(src));
 
-        let pstr_loc = heap_index!(self.cell_len());
-
-        Ok(if size_in_heap > 0 {
-            let mut writer = self.reserve(size_in_heap)?;
-
-            writer.write_with(|section| {
-                section.push_pstr(src);
-            });
-
-            Some(PStrWriteInfo { pstr_loc })
-        } else {
-            None
-        })
+        Ok(result.map(|cell| PStrWriteInfo { cell }))
     }
 
     pub const fn heap_cell_alignment() -> usize {
@@ -1053,7 +1055,8 @@ impl Heap {
         move |heap| {
             let mut writer = heap.reserve(size)?;
             let heap_byte_len = *writer.heap_byte_len;
-            let bytes_written = writer.write_with(&mut functor_writer);
+            let HeapSectionWriteResult { bytes_written, .. } =
+                writer.write_with(&mut functor_writer);
 
             Ok(if cell_index!(bytes_written) > 1 {
                 str_loc_as_cell!(cell_index!(heap_byte_len))
@@ -1108,19 +1111,18 @@ impl MachineState {
     pub(crate) fn allocate_pstr(&mut self, src: &str) -> Result<HeapCellValue, usize> {
         match self.heap.allocate_pstr(src)? {
             None => Ok(empty_list_as_cell!()),
-            Some(PStrWriteInfo { pstr_loc, .. }) => Ok(pstr_loc_as_cell!(pstr_loc)),
+            Some(PStrWriteInfo { cell }) => Ok(cell),
         }
     }
 
-    // note that allocate_cstr does emit a tail cell to the string
-    // (completing it with the empty list), allocate_pstr does not, in
-    // any incarnation.
+    // note that allocate_cstr emits a tail cell to the string (completing it with the empty list)
+    // unlike any version of allocate_pstr.
     pub(crate) fn allocate_cstr(&mut self, src: &str) -> Result<HeapCellValue, usize> {
         match self.heap.allocate_pstr(src)? {
             None => Ok(empty_list_as_cell!()),
-            Some(PStrWriteInfo { pstr_loc, .. }) => {
+            Some(PStrWriteInfo { cell }) => {
                 self.heap.push_cell(empty_list_as_cell!())?;
-                Ok(pstr_loc_as_cell!(pstr_loc))
+                Ok(cell)
             }
         }
     }
@@ -1281,17 +1283,3 @@ pub(crate) fn to_local_code_ptr(heap: &Heap, addr: HeapCellValue) -> Option<usiz
         }
     )
 }
-
-#[cfg(test)]
-mod test {
-    use super::*;
-
-    #[test]
-    fn heap_manipulation() {
-        let mut heap = Heap::new();
-
-        for idx in 0 .. 10 {
-            heap.push_cell(heap_loc_as_cell!(idx)).unwrap();
-        }
-    }
-}
index dcf7a9201fd85640b19393ee74b8caefc681c1c5..8c50c12853a058292cee64e013f4fcfbc36668a4 100644 (file)
@@ -289,10 +289,13 @@ impl Ball {
         while pstr_threshold < heap_index!(self.stub.cell_len()) {
             let HeapStringScan { string, tail_idx } = self.stub.scan_slice_to_str(pstr_threshold);
 
-            pstr_threshold += dest_writer.write_with(|section| {
-                section.push_pstr(string).unwrap();
-                section.push_cell(self.stub[tail_idx] - diff);
-            });
+            pstr_threshold += dest_writer
+                .write_with(|section| {
+                    if section.push_pstr(string).is_some() {
+                        section.push_cell(self.stub[tail_idx] - diff);
+                    }
+                })
+                .bytes_written;
         }
 
         Ok(h)
index a13b0d579179fb80bccb6d47cd67cc8b754861f0..0dcff8a7fb2096ebe5cdbb8a5039eb3ed465a402 100644 (file)
@@ -662,24 +662,36 @@ impl<'a> Parser<'a> {
 
                     match as_partial_string(&self.terms, head, tail) {
                         Some((string_buf, tail_opt)) => {
-                            let bytes_written = self.terms.write_with(|section| {
-                                let pstr_cell = section.push_pstr(&string_buf).unwrap();
-                                section.push_cell(tail_opt.unwrap_or(empty_list_as_cell!()));
-                                section.push_cell(pstr_cell);
-                            });
-
-                            let heap_loc = cell_index!(bytes_written) - 1 + cell_len;
-
-                            TokenType::Term {
-                                heap_loc: heap_loc_as_cell!(heap_loc),
+                            let HeapSectionWriteResult { bytes_written, .. } =
+                                self.terms.write_with(|section| {
+                                    if let Some(pstr_cell) = section.push_pstr(&string_buf) {
+                                        section
+                                            .push_cell(tail_opt.unwrap_or(empty_list_as_cell!()));
+                                        section.push_cell(pstr_cell);
+                                    } else {
+                                        section.push_cell(empty_list_as_cell!());
+                                    }
+                                });
+
+                            if cell_index!(bytes_written) > 1 {
+                                TokenType::Term {
+                                    heap_loc: heap_loc_as_cell!(
+                                        cell_index!(bytes_written) - 1 + cell_len
+                                    ),
+                                }
+                            } else {
+                                TokenType::Term {
+                                    heap_loc: heap_loc_as_cell!(cell_len),
+                                }
                             }
                         }
                         None => {
-                            let bytes_written = self.terms.write_with(|section| {
-                                section.push_cell(head);
-                                section.push_cell(tail);
-                                section.push_cell(list_loc_as_cell!(term_idx));
-                            });
+                            let HeapSectionWriteResult { bytes_written, .. } =
+                                self.terms.write_with(|section| {
+                                    section.push_cell(head);
+                                    section.push_cell(tail);
+                                    section.push_cell(list_loc_as_cell!(term_idx));
+                                });
 
                             TokenType::Term {
                                 heap_loc: heap_loc_as_cell!(
@@ -911,13 +923,19 @@ impl<'a> Parser<'a> {
             Some((string_buf, tail_opt)) => {
                 self.terms.truncate(pre_terms_len);
 
-                let bytes_written = self.terms.write_with(|section| {
-                    let pstr_cell = section.push_pstr(&string_buf).unwrap();
-                    section.push_cell(tail_opt.unwrap_or(empty_list_as_cell!()));
-                    section.push_cell(pstr_cell);
-                });
+                let HeapSectionWriteResult { bytes_written, .. } =
+                    self.terms.write_with(|section| {
+                        if let Some(pstr_cell) = section.push_pstr(&string_buf) {
+                            section.push_cell(tail_opt.unwrap_or(empty_list_as_cell!()));
+                            section.push_cell(pstr_cell);
+                        }
+                    });
 
-                heap_loc_as_cell!(pre_terms_len + cell_index!(bytes_written) - 1)
+                if bytes_written > 0 {
+                    heap_loc_as_cell!(pre_terms_len + cell_index!(bytes_written) - 1)
+                } else {
+                    empty_list_as_cell!()
+                }
             }
             None => {
                 heap_loc_as_cell!(list_loc) // head_term