make write_with forward return values, use it to correct partial string handling
This commit is contained in:
@@ -183,7 +183,7 @@ impl PStrSegmentCmpResult {
|
|||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct PStrWriteInfo {
|
pub struct PStrWriteInfo {
|
||||||
pstr_loc: usize,
|
cell: HeapCellValue,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
@@ -414,29 +414,40 @@ pub struct HeapWriter<'a> {
|
|||||||
heap_byte_len: &'a mut usize,
|
heap_byte_len: &'a mut usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) struct HeapSectionWriteResult<R> {
|
||||||
|
pub(crate) bytes_written: usize,
|
||||||
|
pub(crate) result: R,
|
||||||
|
}
|
||||||
|
|
||||||
impl<'a> HeapWriter<'a> {
|
impl<'a> HeapWriter<'a> {
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub(crate) fn write_with_error_handling<E>(
|
pub(crate) fn write_with_error_handling<R, E>(
|
||||||
&mut self,
|
&mut self,
|
||||||
writer: impl FnOnce(&mut ReservedHeapSection) -> Result<(), E>,
|
writer: impl FnOnce(&mut ReservedHeapSection) -> Result<R, E>,
|
||||||
) -> Result<usize, E> {
|
) -> Result<HeapSectionWriteResult<R>, E> {
|
||||||
let old_section_cell_len = self.section.heap_cell_len;
|
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);
|
*self.heap_byte_len = heap_index!(self.section.heap_cell_len);
|
||||||
|
|
||||||
// return the number of bytes written
|
// return the number of bytes written
|
||||||
Ok(heap_index!(
|
Ok(HeapSectionWriteResult {
|
||||||
self.section.heap_cell_len - old_section_cell_len
|
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;
|
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);
|
*self.heap_byte_len = heap_index!(self.section.heap_cell_len);
|
||||||
|
|
||||||
// return the number of bytes written
|
HeapSectionWriteResult {
|
||||||
heap_index!(self.section.heap_cell_len - old_section_cell_len)
|
bytes_written: heap_index!(self.section.heap_cell_len - old_section_cell_len),
|
||||||
|
result,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
@@ -854,20 +865,11 @@ impl Heap {
|
|||||||
|
|
||||||
pub fn allocate_pstr(&mut self, src: &str) -> Result<Option<PStrWriteInfo>, usize> {
|
pub fn allocate_pstr(&mut self, src: &str) -> Result<Option<PStrWriteInfo>, usize> {
|
||||||
let size_in_heap = Self::compute_pstr_size(src);
|
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(result.map(|cell| PStrWriteInfo { cell }))
|
||||||
|
|
||||||
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
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const fn heap_cell_alignment() -> usize {
|
pub const fn heap_cell_alignment() -> usize {
|
||||||
@@ -1053,7 +1055,8 @@ impl Heap {
|
|||||||
move |heap| {
|
move |heap| {
|
||||||
let mut writer = heap.reserve(size)?;
|
let mut writer = heap.reserve(size)?;
|
||||||
let heap_byte_len = *writer.heap_byte_len;
|
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 {
|
Ok(if cell_index!(bytes_written) > 1 {
|
||||||
str_loc_as_cell!(cell_index!(heap_byte_len))
|
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> {
|
pub(crate) fn allocate_pstr(&mut self, src: &str) -> Result<HeapCellValue, usize> {
|
||||||
match self.heap.allocate_pstr(src)? {
|
match self.heap.allocate_pstr(src)? {
|
||||||
None => Ok(empty_list_as_cell!()),
|
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
|
// note that allocate_cstr emits a tail cell to the string (completing it with the empty list)
|
||||||
// (completing it with the empty list), allocate_pstr does not, in
|
// unlike any version of allocate_pstr.
|
||||||
// any incarnation.
|
|
||||||
pub(crate) fn allocate_cstr(&mut self, src: &str) -> Result<HeapCellValue, usize> {
|
pub(crate) fn allocate_cstr(&mut self, src: &str) -> Result<HeapCellValue, usize> {
|
||||||
match self.heap.allocate_pstr(src)? {
|
match self.heap.allocate_pstr(src)? {
|
||||||
None => Ok(empty_list_as_cell!()),
|
None => Ok(empty_list_as_cell!()),
|
||||||
Some(PStrWriteInfo { pstr_loc, .. }) => {
|
Some(PStrWriteInfo { cell }) => {
|
||||||
self.heap.push_cell(empty_list_as_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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -289,10 +289,13 @@ impl Ball {
|
|||||||
while pstr_threshold < heap_index!(self.stub.cell_len()) {
|
while pstr_threshold < heap_index!(self.stub.cell_len()) {
|
||||||
let HeapStringScan { string, tail_idx } = self.stub.scan_slice_to_str(pstr_threshold);
|
let HeapStringScan { string, tail_idx } = self.stub.scan_slice_to_str(pstr_threshold);
|
||||||
|
|
||||||
pstr_threshold += dest_writer.write_with(|section| {
|
pstr_threshold += dest_writer
|
||||||
section.push_pstr(string).unwrap();
|
.write_with(|section| {
|
||||||
section.push_cell(self.stub[tail_idx] - diff);
|
if section.push_pstr(string).is_some() {
|
||||||
});
|
section.push_cell(self.stub[tail_idx] - diff);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.bytes_written;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(h)
|
Ok(h)
|
||||||
|
|||||||
@@ -662,24 +662,36 @@ impl<'a> Parser<'a> {
|
|||||||
|
|
||||||
match as_partial_string(&self.terms, head, tail) {
|
match as_partial_string(&self.terms, head, tail) {
|
||||||
Some((string_buf, tail_opt)) => {
|
Some((string_buf, tail_opt)) => {
|
||||||
let bytes_written = self.terms.write_with(|section| {
|
let HeapSectionWriteResult { bytes_written, .. } =
|
||||||
let pstr_cell = section.push_pstr(&string_buf).unwrap();
|
self.terms.write_with(|section| {
|
||||||
section.push_cell(tail_opt.unwrap_or(empty_list_as_cell!()));
|
if let Some(pstr_cell) = section.push_pstr(&string_buf) {
|
||||||
section.push_cell(pstr_cell);
|
section
|
||||||
});
|
.push_cell(tail_opt.unwrap_or(empty_list_as_cell!()));
|
||||||
|
section.push_cell(pstr_cell);
|
||||||
|
} else {
|
||||||
|
section.push_cell(empty_list_as_cell!());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
let heap_loc = cell_index!(bytes_written) - 1 + cell_len;
|
if cell_index!(bytes_written) > 1 {
|
||||||
|
TokenType::Term {
|
||||||
TokenType::Term {
|
heap_loc: heap_loc_as_cell!(
|
||||||
heap_loc: heap_loc_as_cell!(heap_loc),
|
cell_index!(bytes_written) - 1 + cell_len
|
||||||
|
),
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
TokenType::Term {
|
||||||
|
heap_loc: heap_loc_as_cell!(cell_len),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
let bytes_written = self.terms.write_with(|section| {
|
let HeapSectionWriteResult { bytes_written, .. } =
|
||||||
section.push_cell(head);
|
self.terms.write_with(|section| {
|
||||||
section.push_cell(tail);
|
section.push_cell(head);
|
||||||
section.push_cell(list_loc_as_cell!(term_idx));
|
section.push_cell(tail);
|
||||||
});
|
section.push_cell(list_loc_as_cell!(term_idx));
|
||||||
|
});
|
||||||
|
|
||||||
TokenType::Term {
|
TokenType::Term {
|
||||||
heap_loc: heap_loc_as_cell!(
|
heap_loc: heap_loc_as_cell!(
|
||||||
@@ -911,13 +923,19 @@ impl<'a> Parser<'a> {
|
|||||||
Some((string_buf, tail_opt)) => {
|
Some((string_buf, tail_opt)) => {
|
||||||
self.terms.truncate(pre_terms_len);
|
self.terms.truncate(pre_terms_len);
|
||||||
|
|
||||||
let bytes_written = self.terms.write_with(|section| {
|
let HeapSectionWriteResult { bytes_written, .. } =
|
||||||
let pstr_cell = section.push_pstr(&string_buf).unwrap();
|
self.terms.write_with(|section| {
|
||||||
section.push_cell(tail_opt.unwrap_or(empty_list_as_cell!()));
|
if let Some(pstr_cell) = section.push_pstr(&string_buf) {
|
||||||
section.push_cell(pstr_cell);
|
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 => {
|
None => {
|
||||||
heap_loc_as_cell!(list_loc) // head_term
|
heap_loc_as_cell!(list_loc) // head_term
|
||||||
|
|||||||
Reference in New Issue
Block a user