#[derive(Debug)]
pub struct PStrWriteInfo {
- pstr_loc: usize,
+ cell: HeapCellValue,
}
#[derive(Debug)]
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]
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 {
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))
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)
}
}
}
}
)
}
-
-#[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();
- }
- }
-}
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!(
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