From 817d8f5b8b76268481d7e23c6227dff077c781bb Mon Sep 17 00:00:00 2001 From: Mark Thom Date: Sat, 15 Mar 2025 02:10:56 -0700 Subject: [PATCH] make write_with forward return values, use it to correct partial string handling --- src/machine/heap.rs | 80 +++++++++++++++--------------------- src/machine/machine_state.rs | 11 +++-- src/parser/parser.rs | 60 +++++++++++++++++---------- 3 files changed, 80 insertions(+), 71 deletions(-) diff --git a/src/machine/heap.rs b/src/machine/heap.rs index d628391c..efd4337c 100644 --- a/src/machine/heap.rs +++ b/src/machine/heap.rs @@ -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 { + pub(crate) bytes_written: usize, + pub(crate) result: R, +} + impl<'a> HeapWriter<'a> { #[allow(dead_code)] - pub(crate) fn write_with_error_handling( + pub(crate) fn write_with_error_handling( &mut self, - writer: impl FnOnce(&mut ReservedHeapSection) -> Result<(), E>, - ) -> Result { + writer: impl FnOnce(&mut ReservedHeapSection) -> Result, + ) -> Result, 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( + &mut self, + writer: impl FnOnce(&mut ReservedHeapSection) -> R, + ) -> HeapSectionWriteResult { 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, 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 { 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 { 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 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 -- 2.54.0