remove pstr_vec
This commit is contained in:
@@ -89,7 +89,7 @@ const INLINED_ATOM_MAX_LEN: usize = 6;
|
||||
fn static_string_index(string: &str, index: usize) -> u64 {
|
||||
if 0 < string.len() && string.len() <= INLINED_ATOM_MAX_LEN {
|
||||
let mut string_buf: [u8; 8] = [0u8; 8];
|
||||
string_buf[.. string.len()].copy_from_slice(string.as_bytes());
|
||||
string_buf[..string.len()].copy_from_slice(string.as_bytes());
|
||||
(u64::from_le_bytes(string_buf) << 1) | 1
|
||||
} else {
|
||||
(index << 1) as u64
|
||||
@@ -165,22 +165,26 @@ pub fn index_static_strings(instruction_rs_path: &std::path::Path) -> TokenStrea
|
||||
let mut static_strs = vec![];
|
||||
let mut static_str_indices = vec![];
|
||||
|
||||
let indices: Vec<u64> = visitor.static_strs.iter().map(|string| {
|
||||
let index = static_string_index(string, static_strs.len());
|
||||
let indices: Vec<u64> = visitor
|
||||
.static_strs
|
||||
.iter()
|
||||
.map(|string| {
|
||||
let index = static_string_index(string, static_strs.len());
|
||||
|
||||
static_str_keys.push(string);
|
||||
static_str_keys.push(string);
|
||||
|
||||
if index & 1 == 1 {
|
||||
index
|
||||
} else {
|
||||
static_str_indices.push(index);
|
||||
static_strs.push(string);
|
||||
index
|
||||
}
|
||||
}).collect();
|
||||
if index & 1 == 1 {
|
||||
index
|
||||
} else {
|
||||
static_str_indices.push(index);
|
||||
static_strs.push(string);
|
||||
index
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
|
||||
let static_strs_len = static_strs.len(); // visitor.static_strs.len();
|
||||
//let static_strs: &Vec<_> = &visitor.static_strs.into_iter().collect();
|
||||
//let static_strs: &Vec<_> = &visitor.static_strs.into_iter().collect();
|
||||
|
||||
quote! {
|
||||
static STRINGS: [&str; #static_strs_len] = [
|
||||
|
||||
@@ -479,7 +479,6 @@ impl Div<Number> for Number {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
impl PartialEq for Number {
|
||||
fn eq(&self, rhs: &Self) -> bool {
|
||||
match (self, rhs) {
|
||||
@@ -563,7 +562,6 @@ impl PartialOrd for Number {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
impl Ord for Number {
|
||||
fn cmp(&self, rhs: &Number) -> Ordering {
|
||||
match (self, rhs) {
|
||||
|
||||
@@ -66,7 +66,7 @@ impl AtomCell {
|
||||
debug_assert!(string.len() <= INLINED_ATOM_MAX_LEN);
|
||||
|
||||
let mut string_buf: [u8; 8] = [0u8; 8];
|
||||
string_buf[.. string.len()].copy_from_slice(string.as_bytes());
|
||||
string_buf[..string.len()].copy_from_slice(string.as_bytes());
|
||||
let encoding = u64::from_le_bytes(string_buf);
|
||||
|
||||
AtomCell::new()
|
||||
@@ -80,7 +80,7 @@ impl AtomCell {
|
||||
|
||||
#[inline]
|
||||
pub fn new_char_inlined(c: char) -> Self {
|
||||
let mut char_buf = [0u8;8];
|
||||
let mut char_buf = [0u8; 8];
|
||||
c.encode_utf8(&mut char_buf);
|
||||
|
||||
let encoding = u64::from_le_bytes(char_buf);
|
||||
@@ -109,7 +109,9 @@ impl AtomCell {
|
||||
|
||||
#[inline]
|
||||
pub fn get_name(self) -> Atom {
|
||||
Atom { index: (self.name() << 1) | self.is_inlined() as u64 }
|
||||
Atom {
|
||||
index: (self.name() << 1) | self.is_inlined() as u64,
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
@@ -216,21 +218,22 @@ impl Hash for Atom {
|
||||
|
||||
pub enum AtomString<'a> {
|
||||
Static(&'a str),
|
||||
Inlined([u8;8]),
|
||||
Inlined([u8; 8]),
|
||||
Dynamic(AtomTableRef<str>),
|
||||
}
|
||||
|
||||
fn inlined_to_str<'a>(bytes: &'a [u8;8]) -> &'a str {
|
||||
fn inlined_to_str<'a>(bytes: &'a [u8; 8]) -> &'a str {
|
||||
// allow the '\0\' atom to be represented as the 0-valued inlined atom
|
||||
let slice_len = if bytes[0] == 0 {
|
||||
1
|
||||
} else {
|
||||
bytes.iter().position(|&b| b == 0u8).unwrap_or(INLINED_ATOM_MAX_LEN)
|
||||
bytes
|
||||
.iter()
|
||||
.position(|&b| b == 0u8)
|
||||
.unwrap_or(INLINED_ATOM_MAX_LEN)
|
||||
};
|
||||
|
||||
unsafe {
|
||||
str::from_utf8_unchecked(&bytes[..slice_len])
|
||||
}
|
||||
unsafe { str::from_utf8_unchecked(&bytes[..slice_len]) }
|
||||
}
|
||||
|
||||
impl std::fmt::Debug for AtomString<'_> {
|
||||
|
||||
164
src/codegen.rs
164
src/codegen.rs
@@ -295,8 +295,10 @@ impl DebrayAllocator {
|
||||
self.mark_var::<QueryInstruction>(var_num, Level::Shallow, context, code);
|
||||
temp_v!(arg)
|
||||
} else {
|
||||
if let VarAlloc::Perm { allocation: PermVarAllocation::Pending, .. } =
|
||||
&self.var_data.records[var_num].allocation
|
||||
if let VarAlloc::Perm {
|
||||
allocation: PermVarAllocation::Pending,
|
||||
..
|
||||
} = &self.var_data.records[var_num].allocation
|
||||
{
|
||||
self.mark_var::<QueryInstruction>(var_num, Level::Shallow, context, code);
|
||||
} else {
|
||||
@@ -337,22 +339,16 @@ impl<'a> AddToFreeList<'a, QueryInstruction> for CodeGenerator {
|
||||
fn add_index_ptr<'a, Target: crate::targets::CompilationTarget<'a>>(
|
||||
index_ptrs: &IndexMap<usize, CodeIndex, FxBuildHasher>,
|
||||
heap: &Heap,
|
||||
arity: usize,
|
||||
heap_loc: usize,
|
||||
) -> Option<Instruction> {
|
||||
match fetch_index_ptr(heap, arity, heap_loc) {
|
||||
Some(index_ptr) => {
|
||||
if let Some(index_ptr) = index_ptrs.get(&heap_loc) {
|
||||
let subterm = HeapCellValue::from(*index_ptr);
|
||||
return Some(Target::constant_subterm(subterm));
|
||||
} else if !heap[heap_loc.saturating_sub(1)].get_mark_bit() {
|
||||
if let Some(index_ptr) = fetch_index_ptr(heap, heap_loc) {
|
||||
let subterm = HeapCellValue::from(index_ptr);
|
||||
return Some(Target::constant_subterm(subterm));
|
||||
}
|
||||
None => {
|
||||
// if Level::Shallow == lvl {
|
||||
if let Some(index_ptr) = index_ptrs.get(&heap_loc) {
|
||||
let subterm = HeapCellValue::from(*index_ptr);
|
||||
return Some(Target::constant_subterm(subterm));
|
||||
}
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
None
|
||||
@@ -495,23 +491,28 @@ impl CodeGenerator {
|
||||
let (heap_loc, _) = subterm_index(iter.deref(), heap_loc);
|
||||
|
||||
if arity == 0 {
|
||||
if let Some(instr) = add_index_ptr::<Target>(index_ptrs, &iter, arity, heap_loc) {
|
||||
if let Some(instr) = add_index_ptr::<Target>(index_ptrs, &iter, heap_loc) {
|
||||
let r = self.marker.mark_non_var::<Target>(lvl, heap_loc, context, &mut target);
|
||||
target.push_back(Target::to_structure(lvl, name, 0, r));
|
||||
target.push_back(instr);
|
||||
target.push_back(Target::to_structure(lvl, name, 0, r));
|
||||
} else if lvl == Level::Shallow {
|
||||
let r = self.marker.mark_non_var::<Target>(lvl, heap_loc, context, &mut target);
|
||||
target.push_back(Target::to_constant(lvl, atom_as_cell!(name), r));
|
||||
}
|
||||
} else {
|
||||
let r = self.marker.mark_non_var::<Target>(lvl, heap_loc, context, &mut target);
|
||||
target.push_back(Target::to_structure(lvl, name, arity, r));
|
||||
|
||||
<CodeGenerator as AddToFreeList<'a, Target>>::add_term_to_free_list(
|
||||
self,
|
||||
r,
|
||||
);
|
||||
|
||||
if let Some(instr) = add_index_ptr::<Target>(index_ptrs, &iter, heap_loc) {
|
||||
target.push_back(instr);
|
||||
}
|
||||
|
||||
target.push_back(Target::to_structure(lvl, name, arity, r));
|
||||
|
||||
let free_list_regs: Vec<_> = (heap_loc + 1 ..= heap_loc + arity)
|
||||
.map(|subterm_loc| {
|
||||
let (subterm_loc, subterm) = subterm_index(iter.deref(), subterm_loc);
|
||||
@@ -522,10 +523,6 @@ impl CodeGenerator {
|
||||
})
|
||||
.collect();
|
||||
|
||||
if let Some(instr) = add_index_ptr::<Target>(index_ptrs, &iter, arity, heap_loc) {
|
||||
target.push_back(instr);
|
||||
}
|
||||
|
||||
for r_opt in free_list_regs {
|
||||
if let Some(r) = r_opt {
|
||||
<CodeGenerator as AddToFreeList<'a, Target>>::add_subterm_to_free_list(
|
||||
@@ -583,11 +580,11 @@ impl CodeGenerator {
|
||||
let heap_loc = iter.focus().value() as usize;
|
||||
let (heap_loc, _) = subterm_index(iter.deref(), heap_loc);
|
||||
let r = self.marker.mark_non_var::<Target>(lvl, heap_loc, context, &mut target);
|
||||
let (pstr_str, tail_loc) = iter.scan_slice_to_str(pstr_loc);
|
||||
let HeapStringScan { string, tail_idx } = iter.scan_slice_to_str(pstr_loc);
|
||||
|
||||
target.push_back(Target::to_pstr(lvl, Rc::new(pstr_str.to_owned()), r));
|
||||
target.push_back(Target::to_pstr(lvl, Rc::new(string.to_owned()), r));
|
||||
|
||||
let (tail_loc, tail) = subterm_index(iter.deref(), tail_loc);
|
||||
let (tail_loc, tail) = subterm_index(iter.deref(), tail_idx);
|
||||
self.subterm_to_instr::<Target>(
|
||||
tail, tail_loc, context, index_ptrs, &mut target,
|
||||
);
|
||||
@@ -676,12 +673,11 @@ impl CodeGenerator {
|
||||
&InlinedClauseType::CompareNumber(mut cmp) => {
|
||||
self.marker.reset_arg(2);
|
||||
|
||||
let (mut lcode, at_1) =
|
||||
if let Some(r) = variable_marker(&mut self.marker) {
|
||||
(CodeDeque::default(), Some(ArithmeticTerm::Reg(r)))
|
||||
} else {
|
||||
self.compile_arith_expr(terms, first_arg_loc, 1, context, 1)?
|
||||
};
|
||||
let (mut lcode, at_1) = if let Some(r) = variable_marker(&mut self.marker) {
|
||||
(CodeDeque::default(), Some(ArithmeticTerm::Reg(r)))
|
||||
} else {
|
||||
self.compile_arith_expr(terms, first_arg_loc, 1, context, 1)?
|
||||
};
|
||||
|
||||
let (mut rcode, at_2) =
|
||||
self.compile_arith_expr(terms, first_arg_loc + 1, 2, context, 2)?;
|
||||
@@ -720,41 +716,41 @@ impl CodeGenerator {
|
||||
if let Some(r) = variable_marker(&mut self.marker) {
|
||||
instr!("atomic", r)
|
||||
} else {
|
||||
read_heap_cell!(first_arg,
|
||||
(HeapCellValueTag::Fixnum |
|
||||
HeapCellValueTag::F64) => {
|
||||
instr!("$succeed")
|
||||
}
|
||||
(HeapCellValueTag::Cons, cons_ptr) => {
|
||||
match cons_ptr.get_tag() {
|
||||
ArenaHeaderTag::Integer | ArenaHeaderTag::Rational => {
|
||||
instr!("$succeed")
|
||||
}
|
||||
_ => {
|
||||
instr!("$fail")
|
||||
}
|
||||
}
|
||||
}
|
||||
(HeapCellValueTag::Atom, (_name, arity)) => {
|
||||
if arity == 0 {
|
||||
instr!("$succeed")
|
||||
} else {
|
||||
instr!("$fail")
|
||||
}
|
||||
}
|
||||
(HeapCellValueTag::Lis
|
||||
| HeapCellValueTag::Str
|
||||
| HeapCellValueTag::PStrLoc) => {
|
||||
instr!("$fail")
|
||||
}
|
||||
_ => {
|
||||
if first_arg.is_constant() {
|
||||
instr!("$succeed")
|
||||
} else {
|
||||
instr!("$fail")
|
||||
}
|
||||
}
|
||||
)
|
||||
read_heap_cell!(first_arg,
|
||||
(HeapCellValueTag::Fixnum |
|
||||
HeapCellValueTag::F64) => {
|
||||
instr!("$succeed")
|
||||
}
|
||||
(HeapCellValueTag::Cons, cons_ptr) => {
|
||||
match cons_ptr.get_tag() {
|
||||
ArenaHeaderTag::Integer | ArenaHeaderTag::Rational => {
|
||||
instr!("$succeed")
|
||||
}
|
||||
_ => {
|
||||
instr!("$fail")
|
||||
}
|
||||
}
|
||||
}
|
||||
(HeapCellValueTag::Atom, (_name, arity)) => {
|
||||
if arity == 0 {
|
||||
instr!("$succeed")
|
||||
} else {
|
||||
instr!("$fail")
|
||||
}
|
||||
}
|
||||
(HeapCellValueTag::Lis
|
||||
| HeapCellValueTag::Str
|
||||
| HeapCellValueTag::PStrLoc) => {
|
||||
instr!("$fail")
|
||||
}
|
||||
_ => {
|
||||
if first_arg.is_constant() {
|
||||
instr!("$succeed")
|
||||
} else {
|
||||
instr!("$fail")
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
InlinedClauseType::IsCompound(..) => {
|
||||
@@ -860,7 +856,7 @@ impl CodeGenerator {
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
InlinedClauseType::IsVar(..) => {
|
||||
self.marker.reset_arg(1);
|
||||
|
||||
@@ -871,7 +867,7 @@ impl CodeGenerator {
|
||||
} else {
|
||||
instr!("$fail")
|
||||
}
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
// inlined predicates are never counted, so this overrides nothing.
|
||||
@@ -901,8 +897,7 @@ impl CodeGenerator {
|
||||
) -> Result<(), CompilationError> {
|
||||
macro_rules! compile_expr {
|
||||
($self:expr, $terms:expr, $context:expr, $code:expr) => {{
|
||||
let (acode, at) =
|
||||
$self.compile_arith_expr($terms, term_loc + 2, 1, $context, 2)?;
|
||||
let (acode, at) = $self.compile_arith_expr($terms, term_loc + 2, 1, $context, 2)?;
|
||||
$code.extend(acode.into_iter());
|
||||
at
|
||||
}};
|
||||
@@ -1067,13 +1062,11 @@ impl CodeGenerator {
|
||||
code.push_back(instr!("deallocate"));
|
||||
}
|
||||
|
||||
code.push_back(
|
||||
if self.marker.in_tail_position {
|
||||
instr!("$succeed").into_execute()
|
||||
} else {
|
||||
instr!("$succeed")
|
||||
},
|
||||
);
|
||||
code.push_back(if self.marker.in_tail_position {
|
||||
instr!("$succeed").into_execute()
|
||||
} else {
|
||||
instr!("$succeed")
|
||||
});
|
||||
}
|
||||
QueryTerm::Clause(clause) => {
|
||||
self.compile_query_line(
|
||||
@@ -1145,7 +1138,10 @@ impl CodeGenerator {
|
||||
|
||||
self.marker.var_data = var_data;
|
||||
|
||||
let term = FocusedHeapRefMut { heap, focus: *term_loc };
|
||||
let term = FocusedHeapRefMut {
|
||||
heap,
|
||||
focus: *term_loc,
|
||||
};
|
||||
let mut code = VecDeque::new();
|
||||
|
||||
let head_loc = term.nth_arg(term.focus, 1).unwrap();
|
||||
@@ -1216,11 +1212,7 @@ impl CodeGenerator {
|
||||
let mut stack = Stack::uninitialized();
|
||||
let iter = query_iterator::<true>(&mut term.heap, &mut stack, clause.term_loc());
|
||||
|
||||
let query = self.compile_target::<QueryInstruction, _>(
|
||||
iter,
|
||||
&clause.code_indices,
|
||||
context,
|
||||
);
|
||||
let query = self.compile_target::<QueryInstruction, _>(iter, &clause.code_indices, context);
|
||||
|
||||
code.extend(query);
|
||||
self.add_call(code, clause.ct.to_instr(), clause.call_policy);
|
||||
@@ -1342,20 +1334,14 @@ impl CodeGenerator {
|
||||
skip_stub_try_me_else = !self.settings.is_dynamic();
|
||||
}
|
||||
|
||||
let arg = clause.args(heap)
|
||||
.map(|r| heap[r.start() + optimal_index]);
|
||||
let arg = clause.args(heap).map(|r| heap[r.start() + optimal_index]);
|
||||
|
||||
if let Some(arg) = arg {
|
||||
let index = code.len();
|
||||
|
||||
if clauses_len > 1 || self.settings.is_extensible {
|
||||
let arg = heap_bound_store(heap, heap_bound_deref(heap, arg));
|
||||
code_offsets.index_term(
|
||||
heap,
|
||||
arg,
|
||||
index,
|
||||
&mut clause_index_info,
|
||||
);
|
||||
code_offsets.index_term(heap, arg, index, &mut clause_index_info);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -172,7 +172,9 @@ impl DebrayAllocator {
|
||||
|
||||
for var_num in subsumed_hits {
|
||||
match &mut self.var_data.records[var_num].allocation {
|
||||
VarAlloc::Perm { ref mut allocation, .. } => {
|
||||
VarAlloc::Perm {
|
||||
ref mut allocation, ..
|
||||
} => {
|
||||
if let PermVarAllocation::Done {
|
||||
shallow_safety,
|
||||
deep_safety,
|
||||
@@ -233,7 +235,7 @@ impl DebrayAllocator {
|
||||
let num_occurrences = self.var_data.records[var_num].num_occurrences;
|
||||
|
||||
match &mut self.var_data.records[var_num].allocation {
|
||||
VarAlloc::Perm { allocation, ..} => {
|
||||
VarAlloc::Perm { allocation, .. } => {
|
||||
let shallow_safety = VarSafetyStatus::needed_if(
|
||||
shallow_safety.contains(var_num),
|
||||
branch_designator,
|
||||
@@ -514,10 +516,12 @@ impl DebrayAllocator {
|
||||
self.perm_free_list.pop_front();
|
||||
|
||||
match &mut self.var_data.records[var_num].allocation {
|
||||
VarAlloc::Perm { reg: p, allocation: PermVarAllocation::Pending }
|
||||
if *p > 0 => {
|
||||
return Some(std::mem::replace(p, 0));
|
||||
}
|
||||
VarAlloc::Perm {
|
||||
reg: p,
|
||||
allocation: PermVarAllocation::Pending,
|
||||
} if *p > 0 => {
|
||||
return Some(std::mem::replace(p, 0));
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
} else {
|
||||
@@ -543,11 +547,12 @@ impl DebrayAllocator {
|
||||
|
||||
match &mut self.var_data.records[var_num].allocation {
|
||||
VarAlloc::Perm {
|
||||
allocation: PermVarAllocation::Done {
|
||||
deep_safety,
|
||||
shallow_safety,
|
||||
..
|
||||
},
|
||||
allocation:
|
||||
PermVarAllocation::Done {
|
||||
deep_safety,
|
||||
shallow_safety,
|
||||
..
|
||||
},
|
||||
..
|
||||
} => {
|
||||
*deep_safety = VarSafetyStatus::unneeded(branch_designator);
|
||||
@@ -568,11 +573,12 @@ impl DebrayAllocator {
|
||||
|
||||
match &mut self.var_data.records[var_num].allocation {
|
||||
VarAlloc::Perm {
|
||||
allocation: PermVarAllocation::Done {
|
||||
deep_safety,
|
||||
shallow_safety,
|
||||
..
|
||||
},
|
||||
allocation:
|
||||
PermVarAllocation::Done {
|
||||
deep_safety,
|
||||
shallow_safety,
|
||||
..
|
||||
},
|
||||
..
|
||||
} => {
|
||||
// GetVariable in head chunk is considered safe.
|
||||
@@ -612,10 +618,11 @@ impl DebrayAllocator {
|
||||
|
||||
match &mut self.var_data.records[var_num].allocation {
|
||||
VarAlloc::Perm {
|
||||
allocation: PermVarAllocation::Done {
|
||||
ref mut shallow_safety,
|
||||
..
|
||||
},
|
||||
allocation:
|
||||
PermVarAllocation::Done {
|
||||
ref mut shallow_safety,
|
||||
..
|
||||
},
|
||||
..
|
||||
} => {
|
||||
if !self.in_tail_position
|
||||
@@ -648,10 +655,11 @@ impl DebrayAllocator {
|
||||
|
||||
match &mut self.var_data.records[var_num].allocation {
|
||||
VarAlloc::Perm {
|
||||
allocation: PermVarAllocation::Done {
|
||||
ref mut deep_safety,
|
||||
..
|
||||
},
|
||||
allocation:
|
||||
PermVarAllocation::Done {
|
||||
ref mut deep_safety,
|
||||
..
|
||||
},
|
||||
..
|
||||
} => {
|
||||
if self
|
||||
@@ -921,10 +929,7 @@ impl Allocator for DebrayAllocator {
|
||||
}
|
||||
|
||||
fn reset_at_head(&mut self, heap: &mut Heap, head_loc: usize) {
|
||||
let head_cell = heap_bound_store(
|
||||
heap,
|
||||
heap_bound_deref(heap, heap_loc_as_cell!(head_loc)),
|
||||
);
|
||||
let head_cell = heap_bound_store(heap, heap_bound_deref(heap, heap_loc_as_cell!(head_loc)));
|
||||
|
||||
read_heap_cell!(head_cell,
|
||||
(HeapCellValueTag::Str, s) => {
|
||||
@@ -933,7 +938,9 @@ impl Allocator for DebrayAllocator {
|
||||
self.reset_arg(arity);
|
||||
self.arity = arity;
|
||||
|
||||
for (idx, arg) in heap.splice(s+1 ..= s+arity).enumerate() {
|
||||
for (c_idx, heap_idx) in (s+1 ..= s+arity).enumerate() {
|
||||
let arg = heap[heap_idx];
|
||||
|
||||
if arg.is_var() {
|
||||
let var = heap_bound_store(
|
||||
heap,
|
||||
@@ -953,11 +960,11 @@ impl Allocator for DebrayAllocator {
|
||||
let r = self.get_var_binding(var_num);
|
||||
|
||||
if !r.is_perm() && r.reg_num() == 0 {
|
||||
self.in_use.insert(idx + 1);
|
||||
self.shallow_temp_mappings.insert(idx + 1, var_num);
|
||||
self.in_use.insert(c_idx + 1);
|
||||
self.shallow_temp_mappings.insert(c_idx + 1, var_num);
|
||||
self.var_data.records[var_num]
|
||||
.allocation
|
||||
.set_register(idx + 1);
|
||||
.set_register(c_idx + 1);
|
||||
}
|
||||
}
|
||||
VarPtr::Anon => {}
|
||||
|
||||
18
src/forms.rs
18
src/forms.rs
@@ -1,7 +1,7 @@
|
||||
use crate::arena::*;
|
||||
use crate::atom_table::*;
|
||||
use crate::instructions::*;
|
||||
use crate::functor_macro::*;
|
||||
use crate::instructions::*;
|
||||
use crate::machine::disjuncts::VarData;
|
||||
use crate::machine::heap::*;
|
||||
// use crate::machine::loader::PredicateQueue;
|
||||
@@ -80,8 +80,8 @@ impl GenContext {
|
||||
#[inline]
|
||||
pub fn chunk_type(&self) -> ChunkType {
|
||||
match self {
|
||||
GenContext::Head => ChunkType::Head,
|
||||
GenContext::Mid(_) => ChunkType::Mid,
|
||||
GenContext::Head => ChunkType::Head,
|
||||
GenContext::Mid(_) => ChunkType::Mid,
|
||||
GenContext::Last(_) => ChunkType::Last,
|
||||
}
|
||||
}
|
||||
@@ -118,7 +118,10 @@ impl ChunkType {
|
||||
#[derive(Debug)]
|
||||
pub enum ChunkedTerms {
|
||||
Branch(Vec<VecDeque<ChunkedTerms>>),
|
||||
Chunk { chunk_num: usize, terms: VecDeque<QueryTerm> },
|
||||
Chunk {
|
||||
chunk_num: usize,
|
||||
terms: VecDeque<QueryTerm>,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
@@ -190,7 +193,8 @@ impl ChunkedTermVec {
|
||||
}
|
||||
|
||||
pub fn current_gen_context(&self) -> GenContext {
|
||||
self.current_chunk_type.to_gen_context(self.current_chunk_num)
|
||||
self.current_chunk_type
|
||||
.to_gen_context(self.current_chunk_num)
|
||||
}
|
||||
|
||||
pub fn push_chunk_term(&mut self, term: QueryTerm) {
|
||||
@@ -290,9 +294,7 @@ pub fn clause_predicate_key(heap: &impl SizedHeap, term_loc: usize) -> Option<Pr
|
||||
let key_opt = term_predicate_key(heap, term_loc);
|
||||
|
||||
if Some((atom!(":-"), 2)) == key_opt {
|
||||
term_nth_arg(heap, term_loc, 1).and_then(|arg_loc| {
|
||||
term_predicate_key(heap, arg_loc)
|
||||
})
|
||||
term_nth_arg(heap, term_loc, 1).and_then(|arg_loc| term_predicate_key(heap, arg_loc))
|
||||
} else {
|
||||
key_opt
|
||||
}
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
//! A macro to construct functor terms ready to be written to the WAM
|
||||
//! heap.
|
||||
|
||||
use crate::atom_table::*;
|
||||
use crate::instructions::IndexingCodePtr;
|
||||
use crate::machine::heap::Heap;
|
||||
@@ -5,7 +8,7 @@ use crate::parser::ast::Fixnum;
|
||||
use crate::types::*;
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub enum FunctorElement {
|
||||
pub(crate) enum FunctorElement {
|
||||
AbsoluteCell(HeapCellValue),
|
||||
Cell(HeapCellValue),
|
||||
InnerFunctor(u64, Vec<FunctorElement>),
|
||||
@@ -190,19 +193,19 @@ pub(crate) fn variadic_functor(
|
||||
let num_items = key_value_pairs.len();
|
||||
|
||||
for (idx, _) in key_value_pairs.iter().enumerate() {
|
||||
arg_vec.push(FunctorElement::Cell(str_loc_as_cell!(2 + num_items * 2 + idx)));
|
||||
arg_vec.push(FunctorElement::Cell(str_loc_as_cell!(
|
||||
2 + num_items * 2 + idx
|
||||
)));
|
||||
arg_vec.push(FunctorElement::Cell(list_loc_as_cell!(5 + idx)));
|
||||
}
|
||||
|
||||
arg_vec.pop();
|
||||
arg_vec.push(FunctorElement::Cell(empty_list_as_cell!()));
|
||||
|
||||
arg_vec.extend(key_value_pairs
|
||||
.into_iter()
|
||||
.map(|kv_func| {
|
||||
let inner_functor_size = cell_index!(Heap::compute_functor_byte_size(&kv_func));
|
||||
FunctorElement::InnerFunctor(inner_functor_size as u64, kv_func)
|
||||
}));
|
||||
arg_vec.extend(key_value_pairs.into_iter().map(|kv_func| {
|
||||
let inner_functor_size = cell_index!(Heap::compute_functor_byte_size(&kv_func));
|
||||
FunctorElement::InnerFunctor(inner_functor_size as u64, kv_func)
|
||||
}));
|
||||
|
||||
arg_vec
|
||||
}
|
||||
@@ -211,13 +214,15 @@ pub(crate) fn variadic_functor(
|
||||
#[allow(unused_parens)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use FunctorElement::*;
|
||||
use std::string::String;
|
||||
use FunctorElement::*;
|
||||
|
||||
#[test]
|
||||
fn basic_terms() {
|
||||
let functor = functor!(atom!("first"), [atom_as_cell((atom!("a"))),
|
||||
char_as_cell('c')]);
|
||||
let functor = functor!(
|
||||
atom!("first"),
|
||||
[atom_as_cell((atom!("a"))), char_as_cell('c')]
|
||||
);
|
||||
|
||||
assert_eq!(functor.len(), 3);
|
||||
|
||||
@@ -225,10 +230,14 @@ mod tests {
|
||||
assert_eq!(functor[1], Cell(atom_as_cell!(atom!("a"))));
|
||||
assert_eq!(functor[2], Cell(char_as_cell!('c')));
|
||||
|
||||
let functor = functor!(atom!("second"), [atom_as_cell((atom!("a"))),
|
||||
functor((atom!("b")), [fixnum(1),
|
||||
fixnum(2)]),
|
||||
char_as_cell('c')]);
|
||||
let functor = functor!(
|
||||
atom!("second"),
|
||||
[
|
||||
atom_as_cell((atom!("a"))),
|
||||
functor((atom!("b")), [fixnum(1), fixnum(2)]),
|
||||
char_as_cell('c')
|
||||
]
|
||||
);
|
||||
|
||||
assert_eq!(functor.len(), 5);
|
||||
|
||||
@@ -236,13 +245,20 @@ mod tests {
|
||||
assert_eq!(functor[1], Cell(atom_as_cell!(atom!("a"))));
|
||||
assert_eq!(functor[2], Cell(str_loc_as_cell!(4)));
|
||||
assert_eq!(functor[3], Cell(char_as_cell!('c')));
|
||||
assert_eq!(functor[4], InnerFunctor(3, functor!(atom!("b"), [fixnum(1),
|
||||
fixnum(2)])));
|
||||
assert_eq!(
|
||||
functor[4],
|
||||
InnerFunctor(3, functor!(atom!("b"), [fixnum(1), fixnum(2)]))
|
||||
);
|
||||
|
||||
let functor = functor!(atom!("third"), [atom_as_cell((atom!("a"))),
|
||||
functor((atom!("b")), [fixnum(1), fixnum(2)]),
|
||||
functor((atom!("c")), [fixnum(1), fixnum(2)]),
|
||||
char_as_cell('c')]);
|
||||
let functor = functor!(
|
||||
atom!("third"),
|
||||
[
|
||||
atom_as_cell((atom!("a"))),
|
||||
functor((atom!("b")), [fixnum(1), fixnum(2)]),
|
||||
functor((atom!("c")), [fixnum(1), fixnum(2)]),
|
||||
char_as_cell('c')
|
||||
]
|
||||
);
|
||||
|
||||
assert_eq!(functor.len(), 7);
|
||||
|
||||
@@ -251,14 +267,25 @@ mod tests {
|
||||
assert_eq!(functor[2], Cell(str_loc_as_cell!(5)));
|
||||
assert_eq!(functor[3], Cell(str_loc_as_cell!(8)));
|
||||
assert_eq!(functor[4], Cell(char_as_cell!('c')));
|
||||
assert_eq!(functor[5], InnerFunctor(3, functor!(atom!("b"), [fixnum(1), fixnum(2)])));
|
||||
assert_eq!(functor[6], InnerFunctor(3, functor!(atom!("c"), [fixnum(1), fixnum(2)])));
|
||||
assert_eq!(
|
||||
functor[5],
|
||||
InnerFunctor(3, functor!(atom!("b"), [fixnum(1), fixnum(2)]))
|
||||
);
|
||||
assert_eq!(
|
||||
functor[6],
|
||||
InnerFunctor(3, functor!(atom!("c"), [fixnum(1), fixnum(2)]))
|
||||
);
|
||||
|
||||
let functor = functor!(atom!("fourth"), [atom_as_cell((atom!("a"))),
|
||||
functor((atom!("b")), [fixnum(1), fixnum(2)]),
|
||||
functor((atom!("c")), [fixnum(1)]),
|
||||
functor((atom!("d")), [fixnum(453), fixnum(2)]),
|
||||
char_as_cell('c')]);
|
||||
let functor = functor!(
|
||||
atom!("fourth"),
|
||||
[
|
||||
atom_as_cell((atom!("a"))),
|
||||
functor((atom!("b")), [fixnum(1), fixnum(2)]),
|
||||
functor((atom!("c")), [fixnum(1)]),
|
||||
functor((atom!("d")), [fixnum(453), fixnum(2)]),
|
||||
char_as_cell('c')
|
||||
]
|
||||
);
|
||||
|
||||
assert_eq!(functor.len(), 9);
|
||||
|
||||
@@ -268,14 +295,26 @@ mod tests {
|
||||
assert_eq!(functor[3], Cell(str_loc_as_cell!(9)));
|
||||
assert_eq!(functor[4], Cell(str_loc_as_cell!(11)));
|
||||
assert_eq!(functor[5], Cell(char_as_cell!('c')));
|
||||
assert_eq!(functor[6], InnerFunctor(3, functor!(atom!("b"), [fixnum(1), fixnum(2)])));
|
||||
assert_eq!(functor[7], InnerFunctor(2, functor!(atom!("c"), [fixnum(1)])));
|
||||
assert_eq!(functor[8], InnerFunctor(3, functor!(atom!("d"), [fixnum(453), fixnum(2)])));
|
||||
assert_eq!(
|
||||
functor[6],
|
||||
InnerFunctor(3, functor!(atom!("b"), [fixnum(1), fixnum(2)]))
|
||||
);
|
||||
assert_eq!(
|
||||
functor[7],
|
||||
InnerFunctor(2, functor!(atom!("c"), [fixnum(1)]))
|
||||
);
|
||||
assert_eq!(
|
||||
functor[8],
|
||||
InnerFunctor(3, functor!(atom!("d"), [fixnum(453), fixnum(2)]))
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn basic_terms_in_heap() {
|
||||
let functor = functor!(atom!("first"), [atom_as_cell((atom!("a"))), char_as_cell('b')]);
|
||||
let functor = functor!(
|
||||
atom!("first"),
|
||||
[atom_as_cell((atom!("a"))), char_as_cell('b')]
|
||||
);
|
||||
|
||||
assert_eq!(functor.len(), 3);
|
||||
|
||||
@@ -291,10 +330,15 @@ mod tests {
|
||||
|
||||
heap.truncate(2);
|
||||
|
||||
let functor = functor!(atom!("second"), [atom_as_cell((atom!("a"))),
|
||||
functor((atom!("b")), [fixnum(1), fixnum(2)]),
|
||||
functor((atom!("c")), [fixnum(1), fixnum(2)]),
|
||||
char_as_cell('b')]);
|
||||
let functor = functor!(
|
||||
atom!("second"),
|
||||
[
|
||||
atom_as_cell((atom!("a"))),
|
||||
functor((atom!("b")), [fixnum(1), fixnum(2)]),
|
||||
functor((atom!("c")), [fixnum(1), fixnum(2)]),
|
||||
char_as_cell('b')
|
||||
]
|
||||
);
|
||||
|
||||
assert_eq!(functor.len(), 7);
|
||||
|
||||
@@ -318,14 +362,24 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn nested_functors() {
|
||||
let functor = functor!(atom!("first"), [atom_as_cell((atom!("a"))),
|
||||
functor((atom!("d")), [fixnum(1),
|
||||
functor((atom!("b")),
|
||||
[atom_as_cell((atom!("c"))),
|
||||
char_as_cell('c')])]),
|
||||
functor((atom!("e")), [fixnum(453),
|
||||
fixnum(2)]),
|
||||
char_as_cell('b')]);
|
||||
let functor = functor!(
|
||||
atom!("first"),
|
||||
[
|
||||
atom_as_cell((atom!("a"))),
|
||||
functor(
|
||||
(atom!("d")),
|
||||
[
|
||||
fixnum(1),
|
||||
functor(
|
||||
(atom!("b")),
|
||||
[atom_as_cell((atom!("c"))), char_as_cell('c')]
|
||||
)
|
||||
]
|
||||
),
|
||||
functor((atom!("e")), [fixnum(453), fixnum(2)]),
|
||||
char_as_cell('b')
|
||||
]
|
||||
);
|
||||
|
||||
assert_eq!(functor.len(), 7);
|
||||
|
||||
@@ -334,24 +388,47 @@ mod tests {
|
||||
assert_eq!(functor[2], Cell(str_loc_as_cell!(5)));
|
||||
assert_eq!(functor[3], Cell(str_loc_as_cell!(11)));
|
||||
assert_eq!(functor[4], Cell(char_as_cell!('b')));
|
||||
assert_eq!(functor[5], InnerFunctor(6, vec![Cell(atom_as_cell!(atom!("d"), 2)),
|
||||
Cell(fixnum_as_cell!(Fixnum::build_with(1))),
|
||||
Cell(str_loc_as_cell!(3)),
|
||||
InnerFunctor(3, functor!(atom!("b"), [atom_as_cell((atom!("c"))),
|
||||
char_as_cell('c')]))]));
|
||||
assert_eq!(functor[6], InnerFunctor(3, functor!(atom!("e"), [fixnum(453),
|
||||
fixnum(2)])));
|
||||
assert_eq!(
|
||||
functor[5],
|
||||
InnerFunctor(
|
||||
6,
|
||||
vec![
|
||||
Cell(atom_as_cell!(atom!("d"), 2)),
|
||||
Cell(fixnum_as_cell!(Fixnum::build_with(1))),
|
||||
Cell(str_loc_as_cell!(3)),
|
||||
InnerFunctor(
|
||||
3,
|
||||
functor!(atom!("b"), [atom_as_cell((atom!("c"))), char_as_cell('c')])
|
||||
)
|
||||
]
|
||||
)
|
||||
);
|
||||
assert_eq!(
|
||||
functor[6],
|
||||
InnerFunctor(3, functor!(atom!("e"), [fixnum(453), fixnum(2)]))
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
#[test]
|
||||
fn nested_functors_in_heap() {
|
||||
let functor = functor!(atom!("first"), [atom_as_cell((atom!("a"))),
|
||||
functor((atom!("second")), [fixnum(1),
|
||||
functor((atom!("third")), [atom_as_cell((atom!("b"))),
|
||||
char_as_cell('c')])]),
|
||||
functor((atom!("fourth")), [fixnum(453), fixnum(2)]),
|
||||
char_as_cell('b')]);
|
||||
let functor = functor!(
|
||||
atom!("first"),
|
||||
[
|
||||
atom_as_cell((atom!("a"))),
|
||||
functor(
|
||||
(atom!("second")),
|
||||
[
|
||||
fixnum(1),
|
||||
functor(
|
||||
(atom!("third")),
|
||||
[atom_as_cell((atom!("b"))), char_as_cell('c')]
|
||||
)
|
||||
]
|
||||
),
|
||||
functor((atom!("fourth")), [fixnum(453), fixnum(2)]),
|
||||
char_as_cell('b')
|
||||
]
|
||||
);
|
||||
|
||||
let mut heap = Heap::new();
|
||||
let mut functor_writer = Heap::functor_writer(functor);
|
||||
@@ -392,33 +469,43 @@ mod tests {
|
||||
|
||||
assert_eq!(heap[0], atom_as_cell!(atom!("first"), 1));
|
||||
assert_eq!(heap[1], pstr_loc_as_cell!(heap_index!(2)));
|
||||
assert_eq!(heap.slice_to_str(heap_index!(2), "a string".len()), "a string");
|
||||
assert_eq!(
|
||||
heap.slice_to_str(heap_index!(2), "a string".len()),
|
||||
"a string"
|
||||
);
|
||||
assert_eq!(heap[4], empty_list_as_cell!());
|
||||
|
||||
heap.truncate(0);
|
||||
|
||||
let functor = functor!(atom!("second"), [string((String::from("a stuttered\0 string")))]);
|
||||
let functor = functor!(
|
||||
atom!("second"),
|
||||
[string((String::from("a stuttered\0 string")))]
|
||||
);
|
||||
|
||||
let mut functor_writer = Heap::functor_writer(functor);
|
||||
functor_writer(&mut heap).unwrap();
|
||||
|
||||
assert_eq!(heap.cell_len(), 7);
|
||||
assert_eq!(heap.cell_len(), 8);
|
||||
|
||||
assert_eq!(heap[0], atom_as_cell!(atom!("second"), 1));
|
||||
assert_eq!(heap[1], pstr_loc_as_cell!(heap_index!(2)));
|
||||
assert_eq!(heap.slice_to_str(heap_index!(2), "a stuttered".len()), "a stuttered");
|
||||
assert_eq!(
|
||||
heap.slice_to_str(heap_index!(2), "a stuttered".len()),
|
||||
"a stuttered"
|
||||
);
|
||||
assert_eq!(heap[4], pstr_loc_as_cell!(heap_index!(5)));
|
||||
assert_eq!(heap.slice_to_str(heap_index!(5), " string".len()), " string");
|
||||
assert_eq!(heap[6], empty_list_as_cell!());
|
||||
assert_eq!(
|
||||
heap.slice_to_str(heap_index!(5), " string".len()),
|
||||
" string"
|
||||
);
|
||||
assert_eq!(heap[7], empty_list_as_cell!());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn functors_with_lists_in_heap() {
|
||||
let functor = functor!(
|
||||
atom!("first"),
|
||||
[list([fixnum(1),
|
||||
atom_as_cell((atom!("a"))),
|
||||
fixnum(2)])]
|
||||
[list([fixnum(1), atom_as_cell((atom!("a"))), fixnum(2)])]
|
||||
);
|
||||
|
||||
assert_eq!(functor.len(), 3);
|
||||
@@ -462,8 +549,10 @@ mod tests {
|
||||
let code_ptr = IndexingCodePtr::Internal(0);
|
||||
let functor = functor!(
|
||||
atom!("first"),
|
||||
[string((String::from("a string"))),
|
||||
indexing_code_ptr(code_ptr)]
|
||||
[
|
||||
string((String::from("a string"))),
|
||||
indexing_code_ptr(code_ptr)
|
||||
]
|
||||
);
|
||||
|
||||
let mut heap = Heap::new();
|
||||
@@ -476,18 +565,30 @@ mod tests {
|
||||
assert_eq!(heap[0], atom_as_cell!(atom!("first"), 2));
|
||||
assert_eq!(heap[1], pstr_loc_as_cell!(heap_index!(3)));
|
||||
assert_eq!(heap[2], str_loc_as_cell!(6));
|
||||
assert_eq!(heap.slice_to_str(heap_index!(3), "a string".len()), "a string");
|
||||
assert_eq!(
|
||||
heap.slice_to_str(heap_index!(3), "a string".len()),
|
||||
"a string"
|
||||
);
|
||||
assert_eq!(heap[5], empty_list_as_cell!());
|
||||
assert_eq!(heap[6], atom_as_cell!(atom!("internal"), 1));
|
||||
assert_eq!(heap[7], fixnum_as_cell!(Fixnum::build_with(0)));
|
||||
|
||||
heap.truncate(0);
|
||||
|
||||
let functor = functor!(atom!("second"),
|
||||
[string((String::from("a string"))),
|
||||
functor((atom!("third")), [atom_as_cell((atom!("a"))),
|
||||
string((String::from("another string"))),
|
||||
indexing_code_ptr(code_ptr)])]);
|
||||
let functor = functor!(
|
||||
atom!("second"),
|
||||
[
|
||||
string((String::from("a string"))),
|
||||
functor(
|
||||
(atom!("third")),
|
||||
[
|
||||
atom_as_cell((atom!("a"))),
|
||||
string((String::from("another string"))),
|
||||
indexing_code_ptr(code_ptr)
|
||||
]
|
||||
)
|
||||
]
|
||||
);
|
||||
|
||||
let mut functor_writer = Heap::functor_writer(functor);
|
||||
functor_writer(&mut heap).unwrap();
|
||||
@@ -497,24 +598,43 @@ mod tests {
|
||||
assert_eq!(heap[0], atom_as_cell!(atom!("second"), 2));
|
||||
assert_eq!(heap[1], pstr_loc_as_cell!(heap_index!(3)));
|
||||
assert_eq!(heap[2], str_loc_as_cell!(6));
|
||||
assert_eq!(heap.slice_to_str(heap_index!(3), "a string".len()), "a string");
|
||||
assert_eq!(
|
||||
heap.slice_to_str(heap_index!(3), "a string".len()),
|
||||
"a string"
|
||||
);
|
||||
assert_eq!(heap[5], empty_list_as_cell!());
|
||||
assert_eq!(heap[6], atom_as_cell!(atom!("third"), 3));
|
||||
assert_eq!(heap[7], atom_as_cell!(atom!("a")));
|
||||
assert_eq!(heap[8], pstr_loc_as_cell!(heap_index!(10)));
|
||||
assert_eq!(heap[9], str_loc_as_cell!(13));
|
||||
assert_eq!(heap.slice_to_str(heap_index!(10), "another string".len()), "another string");
|
||||
assert_eq!(
|
||||
heap.slice_to_str(heap_index!(10), "another string".len()),
|
||||
"another string"
|
||||
);
|
||||
assert_eq!(heap[12], empty_list_as_cell!());
|
||||
assert_eq!(heap[13], atom_as_cell!(atom!("internal"), 1));
|
||||
assert_eq!(heap[14], fixnum_as_cell!(Fixnum::build_with(0)));
|
||||
|
||||
let functor = functor!(atom!("fourth"),
|
||||
[string((String::from("a string"))),
|
||||
functor((atom!("a")),
|
||||
[functor((atom!("fifth")), [fixnum(5),
|
||||
string((String::from("another string"))),
|
||||
indexing_code_ptr(code_ptr)]),
|
||||
string((String::from("and another")))])]);
|
||||
let functor = functor!(
|
||||
atom!("fourth"),
|
||||
[
|
||||
string((String::from("a string"))),
|
||||
functor(
|
||||
(atom!("a")),
|
||||
[
|
||||
functor(
|
||||
(atom!("fifth")),
|
||||
[
|
||||
fixnum(5),
|
||||
string((String::from("another string"))),
|
||||
indexing_code_ptr(code_ptr)
|
||||
]
|
||||
),
|
||||
string((String::from("and another")))
|
||||
]
|
||||
)
|
||||
]
|
||||
);
|
||||
|
||||
heap.truncate(0);
|
||||
|
||||
@@ -526,7 +646,10 @@ mod tests {
|
||||
assert_eq!(heap[0], atom_as_cell!(atom!("fourth"), 2));
|
||||
assert_eq!(heap[1], pstr_loc_as_cell!(heap_index!(3)));
|
||||
assert_eq!(heap[2], str_loc_as_cell!(6));
|
||||
assert_eq!(heap.slice_to_str(heap_index!(3), "a string".len()), "a string");
|
||||
assert_eq!(
|
||||
heap.slice_to_str(heap_index!(3), "a string".len()),
|
||||
"a string"
|
||||
);
|
||||
assert_eq!(heap[5], empty_list_as_cell!());
|
||||
assert_eq!(heap[6], atom_as_cell!(atom!("a"), 2));
|
||||
assert_eq!(heap[7], str_loc_as_cell!(9));
|
||||
@@ -535,11 +658,17 @@ mod tests {
|
||||
assert_eq!(heap[10], fixnum_as_cell!(Fixnum::build_with(5)));
|
||||
assert_eq!(heap[11], pstr_loc_as_cell!(heap_index!(13)));
|
||||
assert_eq!(heap[12], str_loc_as_cell!(16));
|
||||
assert_eq!(heap.slice_to_str(heap_index!(13), "another string".len()), "another string");
|
||||
assert_eq!(
|
||||
heap.slice_to_str(heap_index!(13), "another string".len()),
|
||||
"another string"
|
||||
);
|
||||
assert_eq!(heap[15], empty_list_as_cell!());
|
||||
assert_eq!(heap[16], atom_as_cell!(atom!("internal"), 1));
|
||||
assert_eq!(heap[17], fixnum_as_cell!(Fixnum::build_with(0)));
|
||||
assert_eq!(heap.slice_to_str(heap_index!(18), "and another".len()), "and another");
|
||||
assert_eq!(
|
||||
heap.slice_to_str(heap_index!(18), "and another".len()),
|
||||
"and another"
|
||||
);
|
||||
assert_eq!(heap[20], empty_list_as_cell!());
|
||||
}
|
||||
|
||||
@@ -550,17 +679,16 @@ mod tests {
|
||||
|
||||
let stub = functor!(
|
||||
atom!("existence_error"),
|
||||
[atom_as_cell((atom!("procedure"))), functor((culprit.clone()))]
|
||||
[
|
||||
atom_as_cell((atom!("procedure"))),
|
||||
functor((culprit.clone()))
|
||||
]
|
||||
);
|
||||
|
||||
println!("{:?}", stub);
|
||||
|
||||
// now the error form
|
||||
let lineless_error_form = functor!(
|
||||
atom!("error"),
|
||||
[functor(stub),
|
||||
functor(culprit)]
|
||||
);
|
||||
let lineless_error_form = functor!(atom!("error"), [functor(stub), functor(culprit)]);
|
||||
|
||||
println!("{:?}", lineless_error_form);
|
||||
|
||||
|
||||
159
src/heap_iter.rs
159
src/heap_iter.rs
@@ -116,10 +116,10 @@ impl<'a> EagerStackfulPreOrderHeapIter<'a> {
|
||||
}
|
||||
}
|
||||
(HeapCellValueTag::PStrLoc, h) => {
|
||||
let (_, tail_loc) = self.heap.scan_slice_to_str(h);
|
||||
let tail_idx = self.heap.scan_slice_to_str(h).tail_idx;
|
||||
|
||||
self.heap[tail_loc].set_mark_bit(self.mark_phase);
|
||||
self.iter_stack.push(self.heap[tail_loc]);
|
||||
self.heap[tail_idx].set_mark_bit(self.mark_phase);
|
||||
self.iter_stack.push(self.heap[tail_idx]);
|
||||
}
|
||||
_ => {
|
||||
}
|
||||
@@ -452,12 +452,12 @@ impl<'a, ElideLists: ListElisionPolicy> StackfulPreOrderHeapIter<'a, ElideLists>
|
||||
}
|
||||
(HeapCellValueTag::PStrLoc, vh) => {
|
||||
let cell = *cell;
|
||||
let (_, tail_loc) = self.heap.scan_slice_to_str(vh);
|
||||
let tail_idx = self.heap.scan_slice_to_str(vh).tail_idx;
|
||||
|
||||
// forward the current PStrLoc cell if the zero
|
||||
// byte at the end of the string buffer
|
||||
// is marked
|
||||
let buf_bytes = self.heap[tail_loc - 1].into_bytes();
|
||||
let buf_bytes = self.heap[tail_idx - 1].into_bytes();
|
||||
|
||||
if buf_bytes[7] != 0u8 {
|
||||
let cell = self.read_cell_mut(h);
|
||||
@@ -469,9 +469,9 @@ impl<'a, ElideLists: ListElisionPolicy> StackfulPreOrderHeapIter<'a, ElideLists>
|
||||
// is never inspected, which it isn't.
|
||||
|
||||
self.push_if_unmarked(
|
||||
IterStackLoc::iterable_loc(tail_loc - 1, HeapOrStackTag::Heap),
|
||||
IterStackLoc::iterable_loc(tail_idx - 1, HeapOrStackTag::Heap),
|
||||
);
|
||||
self.stack.push(IterStackLoc::mark_loc(tail_loc, HeapOrStackTag::Heap));
|
||||
self.stack.push(IterStackLoc::mark_loc(tail_idx, HeapOrStackTag::Heap));
|
||||
|
||||
return Some(cell);
|
||||
}
|
||||
@@ -502,7 +502,6 @@ impl<'a, ElideLists: ListElisionPolicy> StackfulPreOrderHeapIter<'a, ElideLists>
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
impl<'a, ElideLists: ListElisionPolicy> Iterator for StackfulPreOrderHeapIter<'a, ElideLists> {
|
||||
type Item = HeapCellValue;
|
||||
|
||||
@@ -707,9 +706,8 @@ mod tests {
|
||||
|
||||
let mut functor_writer = Heap::functor_writer(functor!(
|
||||
f_atom,
|
||||
[atom_as_cell(a_atom),
|
||||
atom_as_cell(b_atom)]),
|
||||
);
|
||||
[atom_as_cell(a_atom), atom_as_cell(b_atom)]
|
||||
));
|
||||
|
||||
let cell = functor_writer(&mut wam.machine_st.heap).unwrap();
|
||||
wam.machine_st.heap.push_cell(cell).unwrap();
|
||||
@@ -733,7 +731,7 @@ mod tests {
|
||||
assert_eq!(iter.next(), None);
|
||||
}
|
||||
|
||||
all_cells_unmarked(wam.machine_st.heap.splice(..));
|
||||
all_cells_unmarked(&wam.machine_st.heap);
|
||||
|
||||
wam.machine_st.heap.clear();
|
||||
|
||||
@@ -758,10 +756,7 @@ mod tests {
|
||||
unmark_cell_bits!(iter.next().unwrap()),
|
||||
atom_as_cell!(f_atom, 4)
|
||||
);
|
||||
assert_eq!(
|
||||
unmark_cell_bits!(iter.next().unwrap()),
|
||||
str_loc_as_cell!(0)
|
||||
);
|
||||
assert_eq!(unmark_cell_bits!(iter.next().unwrap()), str_loc_as_cell!(0));
|
||||
assert_eq!(
|
||||
unmark_cell_bits!(iter.next().unwrap()),
|
||||
atom_as_cell!(a_atom)
|
||||
@@ -778,7 +773,7 @@ mod tests {
|
||||
assert_eq!(iter.next(), None);
|
||||
}
|
||||
|
||||
all_cells_unmarked(wam.machine_st.heap.splice(..));
|
||||
all_cells_unmarked(&wam.machine_st.heap);
|
||||
|
||||
wam.machine_st.heap.clear();
|
||||
|
||||
@@ -794,7 +789,7 @@ mod tests {
|
||||
assert_eq!(iter.next(), None);
|
||||
}
|
||||
|
||||
all_cells_unmarked(wam.machine_st.heap.splice(..));
|
||||
all_cells_unmarked(&wam.machine_st.heap);
|
||||
|
||||
wam.machine_st.heap.clear();
|
||||
|
||||
@@ -837,7 +832,7 @@ mod tests {
|
||||
assert_eq!(iter.next(), None);
|
||||
}
|
||||
|
||||
all_cells_unmarked(wam.machine_st.heap.splice(..));
|
||||
all_cells_unmarked(&wam.machine_st.heap);
|
||||
|
||||
// now make the list cyclic.
|
||||
wam.machine_st.heap[4] = heap_loc_as_cell!(0);
|
||||
@@ -939,8 +934,6 @@ mod tests {
|
||||
assert_eq!(iter.next(), None);
|
||||
}
|
||||
|
||||
all_cells_unmarked(wam.machine_st.heap.splice(..));
|
||||
|
||||
wam.machine_st.heap.clear();
|
||||
|
||||
let mut writer = wam.machine_st.heap.reserve(96).unwrap();
|
||||
@@ -955,9 +948,11 @@ mod tests {
|
||||
|
||||
let mut functor_writer = Heap::functor_writer(functor!(
|
||||
f_atom,
|
||||
[atom_as_cell(a_atom),
|
||||
atom_as_cell(b_atom),
|
||||
atom_as_cell(b_atom)]
|
||||
[
|
||||
atom_as_cell(a_atom),
|
||||
atom_as_cell(b_atom),
|
||||
atom_as_cell(b_atom)
|
||||
]
|
||||
));
|
||||
|
||||
functor_writer(&mut wam.machine_st.heap).unwrap();
|
||||
@@ -1003,7 +998,7 @@ mod tests {
|
||||
assert_eq!(iter.next(), None);
|
||||
}
|
||||
|
||||
all_cells_unmarked(wam.machine_st.heap.splice(..));
|
||||
all_cells_unmarked(&wam.machine_st.heap);
|
||||
|
||||
{
|
||||
let mut iter = stackless_preorder_iter(&mut wam.machine_st.heap, 0);
|
||||
@@ -1044,7 +1039,7 @@ mod tests {
|
||||
// instance.
|
||||
}
|
||||
|
||||
all_cells_unmarked(wam.machine_st.heap.splice(..));
|
||||
all_cells_unmarked(&wam.machine_st.heap);
|
||||
|
||||
assert_eq!(wam.machine_st.heap[0], list_loc_as_cell!(1));
|
||||
assert_eq!(wam.machine_st.heap[1], str_loc_as_cell!(5));
|
||||
@@ -1074,7 +1069,7 @@ mod tests {
|
||||
// instance.
|
||||
}
|
||||
|
||||
all_cells_unmarked(wam.machine_st.heap.splice(..));
|
||||
all_cells_unmarked(&wam.machine_st.heap);
|
||||
|
||||
assert_eq!(wam.machine_st.heap[0], list_loc_as_cell!(1));
|
||||
assert_eq!(wam.machine_st.heap[1], str_loc_as_cell!(5));
|
||||
@@ -1126,7 +1121,7 @@ mod tests {
|
||||
assert_eq!(iter.next(), None);
|
||||
}
|
||||
|
||||
all_cells_unmarked(wam.machine_st.heap.splice(..));
|
||||
all_cells_unmarked(&wam.machine_st.heap);
|
||||
|
||||
wam.machine_st.heap.clear();
|
||||
|
||||
@@ -1147,7 +1142,7 @@ mod tests {
|
||||
assert_eq!(iter.next(), None);
|
||||
}
|
||||
|
||||
all_cells_unmarked(wam.machine_st.heap.splice(..));
|
||||
all_cells_unmarked(&wam.machine_st.heap);
|
||||
|
||||
assert_eq!(
|
||||
unmark_cell_bits!(wam.machine_st.heap[0]),
|
||||
@@ -1193,7 +1188,7 @@ mod tests {
|
||||
assert_eq!(iter.next(), None);
|
||||
}
|
||||
|
||||
all_cells_unmarked(wam.machine_st.heap.splice(..));
|
||||
all_cells_unmarked(&wam.machine_st.heap);
|
||||
|
||||
assert_eq!(
|
||||
unmark_cell_bits!(wam.machine_st.heap[0]),
|
||||
@@ -1427,7 +1422,10 @@ mod tests {
|
||||
wam.machine_st.heap.clear();
|
||||
|
||||
{
|
||||
wam.machine_st.heap.push_cell(fixnum_as_cell!(Fixnum::build_with(0))).unwrap();
|
||||
wam.machine_st
|
||||
.heap
|
||||
.push_cell(fixnum_as_cell!(Fixnum::build_with(0)))
|
||||
.unwrap();
|
||||
|
||||
let mut iter = stackless_preorder_iter(&mut wam.machine_st.heap, 0);
|
||||
|
||||
@@ -1439,7 +1437,7 @@ mod tests {
|
||||
assert_eq!(iter.next(), None);
|
||||
}
|
||||
|
||||
all_cells_unmarked(wam.machine_st.heap.splice(..));
|
||||
all_cells_unmarked(&wam.machine_st.heap);
|
||||
|
||||
wam.machine_st.heap.clear();
|
||||
|
||||
@@ -1473,7 +1471,7 @@ mod tests {
|
||||
assert!(iter.next().is_none());
|
||||
}
|
||||
|
||||
all_cells_unmarked(wam.machine_st.heap.splice(..));
|
||||
all_cells_unmarked(&wam.machine_st.heap);
|
||||
|
||||
wam.machine_st.heap.clear();
|
||||
|
||||
@@ -1504,7 +1502,7 @@ mod tests {
|
||||
assert!(iter.next().is_none());
|
||||
}
|
||||
|
||||
all_cells_unmarked(wam.machine_st.heap.splice(..));
|
||||
all_cells_unmarked(&wam.machine_st.heap);
|
||||
|
||||
wam.machine_st.heap.clear();
|
||||
|
||||
@@ -1564,7 +1562,7 @@ mod tests {
|
||||
assert!(iter.next().is_none());
|
||||
}
|
||||
|
||||
all_cells_unmarked(wam.machine_st.heap.splice(..));
|
||||
all_cells_unmarked(&wam.machine_st.heap);
|
||||
|
||||
assert_eq!(wam.machine_st.heap[0], str_loc_as_cell!(1));
|
||||
assert_eq!(wam.machine_st.heap[1], atom_as_cell!(atom!("g"), 2));
|
||||
@@ -1634,13 +1632,6 @@ mod tests {
|
||||
{
|
||||
let mut iter = stackless_preorder_iter(&mut wam.machine_st.heap, 9);
|
||||
|
||||
/*
|
||||
while let Some(_) = iter.next() {
|
||||
print_heap_terms(iter.heap.iter(), 0);
|
||||
println!("");
|
||||
}
|
||||
*/
|
||||
|
||||
assert_eq!(
|
||||
unmark_cell_bits!(iter.next().unwrap()),
|
||||
list_loc_as_cell!(7)
|
||||
@@ -1693,9 +1684,8 @@ mod tests {
|
||||
|
||||
let mut functor_writer = Heap::functor_writer(functor!(
|
||||
f_atom,
|
||||
[atom_as_cell(a_atom),
|
||||
atom_as_cell(b_atom)]),
|
||||
);
|
||||
[atom_as_cell(a_atom), atom_as_cell(b_atom)]
|
||||
));
|
||||
|
||||
let cell = functor_writer(&mut wam.machine_st.heap).unwrap();
|
||||
let h = wam.machine_st.heap.cell_len();
|
||||
@@ -1924,7 +1914,7 @@ mod tests {
|
||||
);
|
||||
}
|
||||
|
||||
all_cells_unmarked(wam.machine_st.heap.splice(..));
|
||||
all_cells_unmarked(&wam.machine_st.heap);
|
||||
|
||||
assert_eq!(wam.machine_st.heap[0], list_loc_as_cell!(1));
|
||||
assert_eq!(wam.machine_st.heap[1], atom_as_cell!(a_atom));
|
||||
@@ -2021,7 +2011,11 @@ mod tests {
|
||||
|
||||
let functor = functor!(
|
||||
f_atom,
|
||||
[atom_as_cell(a_atom), atom_as_cell(b_atom), atom_as_cell(b_atom)]
|
||||
[
|
||||
atom_as_cell(a_atom),
|
||||
atom_as_cell(b_atom),
|
||||
atom_as_cell(b_atom)
|
||||
]
|
||||
);
|
||||
|
||||
let mut writer = wam.machine_st.heap.reserve(96).unwrap();
|
||||
@@ -2098,7 +2092,7 @@ mod tests {
|
||||
assert_eq!(iter.next(), None);
|
||||
}
|
||||
|
||||
all_cells_unmarked(wam.machine_st.heap.splice(..));
|
||||
all_cells_unmarked(&wam.machine_st.heap);
|
||||
|
||||
wam.machine_st.heap[4] = list_loc_as_cell!(1);
|
||||
|
||||
@@ -2163,7 +2157,7 @@ mod tests {
|
||||
assert_eq!(iter.next(), None);
|
||||
}
|
||||
|
||||
all_cells_unmarked(wam.machine_st.heap.splice(..));
|
||||
all_cells_unmarked(&wam.machine_st.heap);
|
||||
|
||||
wam.machine_st.heap.clear();
|
||||
|
||||
@@ -2202,7 +2196,7 @@ mod tests {
|
||||
assert_eq!(iter.next(), None);
|
||||
}
|
||||
|
||||
all_cells_unmarked(wam.machine_st.heap.splice(..));
|
||||
all_cells_unmarked(&wam.machine_st.heap);
|
||||
|
||||
wam.machine_st.heap.clear();
|
||||
|
||||
@@ -2221,18 +2215,18 @@ mod tests {
|
||||
2,
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
iter.heap.slice_to_str(0, "a string".len()),
|
||||
"a string"
|
||||
);
|
||||
assert_eq!(
|
||||
iter.next().unwrap(),
|
||||
empty_list_as_cell!()
|
||||
);
|
||||
assert_eq!(iter.heap.slice_to_str(0, "a string".len()), "a string");
|
||||
assert_eq!(iter.next().unwrap(), empty_list_as_cell!());
|
||||
assert_eq!(iter.next(), None);
|
||||
}
|
||||
|
||||
all_cells_unmarked(wam.machine_st.heap.splice(..));
|
||||
assert_eq!(wam.machine_st.heap.slice_to_str(0, "a string".len()), "a string");
|
||||
assert_eq!(wam.machine_st.heap[1], HeapCellValue::build_with(HeapCellValueTag::Cons, 0));
|
||||
|
||||
for idx in 2 ..= 3 {
|
||||
assert!(!wam.machine_st.heap[idx].get_mark_bit());
|
||||
assert!(!wam.machine_st.heap[idx].get_forwarding_bit());
|
||||
}
|
||||
|
||||
wam.machine_st.heap.clear();
|
||||
|
||||
@@ -2291,9 +2285,8 @@ mod tests {
|
||||
|
||||
let mut functor_writer = Heap::functor_writer(functor!(
|
||||
f_atom,
|
||||
[atom_as_cell(a_atom),
|
||||
atom_as_cell(b_atom)]),
|
||||
);
|
||||
[atom_as_cell(a_atom), atom_as_cell(b_atom)]
|
||||
));
|
||||
|
||||
let cell = functor_writer(&mut wam.machine_st.heap).unwrap();
|
||||
let h = wam.machine_st.heap.cell_len();
|
||||
@@ -2325,7 +2318,6 @@ mod tests {
|
||||
|
||||
wam.machine_st.heap.clear();
|
||||
|
||||
|
||||
let mut functor_writer = Heap::functor_writer(functor!(
|
||||
f_atom,
|
||||
[
|
||||
@@ -2361,10 +2353,7 @@ mod tests {
|
||||
unmark_cell_bits!(iter.next().unwrap()),
|
||||
atom_as_cell!(a_atom)
|
||||
);
|
||||
assert_eq!(
|
||||
unmark_cell_bits!(iter.next().unwrap()),
|
||||
str_loc_as_cell!(0)
|
||||
);
|
||||
assert_eq!(unmark_cell_bits!(iter.next().unwrap()), str_loc_as_cell!(0));
|
||||
assert_eq!(
|
||||
unmark_cell_bits!(iter.next().unwrap()),
|
||||
atom_as_cell!(f_atom, 4)
|
||||
@@ -2519,7 +2508,7 @@ mod tests {
|
||||
);
|
||||
}
|
||||
|
||||
all_cells_unmarked(wam.machine_st.heap.splice(..));
|
||||
all_cells_unmarked(&wam.machine_st.heap);
|
||||
|
||||
assert_eq!(wam.machine_st.heap[0], list_loc_as_cell!(1));
|
||||
assert_eq!(wam.machine_st.heap[1], atom_as_cell!(a_atom));
|
||||
@@ -2616,7 +2605,11 @@ mod tests {
|
||||
|
||||
let functor = functor!(
|
||||
f_atom,
|
||||
[atom_as_cell(a_atom), atom_as_cell(b_atom), atom_as_cell(b_atom)]
|
||||
[
|
||||
atom_as_cell(a_atom),
|
||||
atom_as_cell(b_atom),
|
||||
atom_as_cell(b_atom)
|
||||
]
|
||||
);
|
||||
|
||||
let mut writer = wam.machine_st.heap.reserve(96).unwrap();
|
||||
@@ -2694,7 +2687,7 @@ mod tests {
|
||||
assert_eq!(iter.next(), None);
|
||||
}
|
||||
|
||||
all_cells_unmarked(wam.machine_st.heap.splice(..));
|
||||
all_cells_unmarked(&wam.machine_st.heap);
|
||||
|
||||
wam.machine_st.heap[4] = list_loc_as_cell!(1);
|
||||
|
||||
@@ -2761,7 +2754,7 @@ mod tests {
|
||||
assert_eq!(iter.next(), None);
|
||||
}
|
||||
|
||||
all_cells_unmarked(wam.machine_st.heap.splice(..));
|
||||
all_cells_unmarked(&wam.machine_st.heap);
|
||||
wam.machine_st.heap.clear();
|
||||
}
|
||||
|
||||
@@ -2778,9 +2771,8 @@ mod tests {
|
||||
|
||||
let mut functor_writer = Heap::functor_writer(functor!(
|
||||
f_atom,
|
||||
[atom_as_cell(a_atom),
|
||||
atom_as_cell(b_atom)]),
|
||||
);
|
||||
[atom_as_cell(a_atom), atom_as_cell(b_atom)]
|
||||
));
|
||||
|
||||
let cell = functor_writer(&mut wam.machine_st.heap).unwrap();
|
||||
wam.machine_st.heap.push_cell(cell).unwrap();
|
||||
@@ -2969,7 +2961,7 @@ mod tests {
|
||||
);
|
||||
}
|
||||
|
||||
all_cells_unmarked(wam.machine_st.heap.splice(..));
|
||||
all_cells_unmarked(&wam.machine_st.heap);
|
||||
|
||||
assert_eq!(wam.machine_st.heap[0], list_loc_as_cell!(1));
|
||||
assert_eq!(wam.machine_st.heap[1], atom_as_cell!(a_atom));
|
||||
@@ -3039,7 +3031,7 @@ mod tests {
|
||||
assert_eq!(iter.next(), None);
|
||||
}
|
||||
|
||||
all_cells_unmarked(wam.machine_st.heap.splice(..));
|
||||
all_cells_unmarked(&wam.machine_st.heap);
|
||||
|
||||
wam.machine_st.heap[4] = pstr_loc_as_cell!(heap_index!(3) + 2);
|
||||
|
||||
@@ -3053,11 +3045,18 @@ mod tests {
|
||||
assert_eq!(iter.next(), None);
|
||||
}
|
||||
|
||||
all_cells_unmarked(wam.machine_st.heap.splice(..));
|
||||
all_cells_unmarked(&wam.machine_st.heap);
|
||||
|
||||
wam.machine_st.heap.clear();
|
||||
|
||||
let functor = functor!(f_atom, [atom_as_cell(a_atom), atom_as_cell(b_atom), atom_as_cell(b_atom)]);
|
||||
let functor = functor!(
|
||||
f_atom,
|
||||
[
|
||||
atom_as_cell(a_atom),
|
||||
atom_as_cell(b_atom),
|
||||
atom_as_cell(b_atom)
|
||||
]
|
||||
);
|
||||
|
||||
let mut writer = wam.machine_st.heap.reserve(96).unwrap();
|
||||
|
||||
@@ -3116,7 +3115,7 @@ mod tests {
|
||||
assert_eq!(iter.next(), None);
|
||||
}
|
||||
|
||||
all_cells_unmarked(wam.machine_st.heap.splice(..));
|
||||
all_cells_unmarked(&wam.machine_st.heap);
|
||||
|
||||
wam.machine_st.heap[4] = list_loc_as_cell!(1);
|
||||
|
||||
@@ -3164,6 +3163,6 @@ mod tests {
|
||||
assert_eq!(iter.next(), None);
|
||||
}
|
||||
|
||||
all_cells_unmarked(wam.machine_st.heap.splice(..));
|
||||
all_cells_unmarked(&wam.machine_st.heap);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -486,7 +486,12 @@ pub struct HCPrinter<'a, Outputter> {
|
||||
pub double_quotes: bool,
|
||||
}
|
||||
|
||||
fn ambiguity_check(outputter: &impl HCValueOutputter, quoted: bool, last_item_idx: usize, atom: &str) -> bool {
|
||||
fn ambiguity_check(
|
||||
outputter: &impl HCValueOutputter,
|
||||
quoted: bool,
|
||||
last_item_idx: usize,
|
||||
atom: &str,
|
||||
) -> bool {
|
||||
let tail = &outputter.as_str()[last_item_idx..];
|
||||
|
||||
if atom == "," || !quoted || non_quoted_token(atom.chars()) {
|
||||
@@ -1132,7 +1137,7 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
|
||||
}
|
||||
|
||||
macro_rules! emit_char {
|
||||
($c:expr) => ({
|
||||
($c:expr) => {{
|
||||
append_str!(self, "'.'");
|
||||
push_char!(self, '(');
|
||||
|
||||
@@ -1141,14 +1146,17 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
|
||||
|
||||
self.state_stack.push(TokenOrRedirect::Close);
|
||||
char_count += 1;
|
||||
});
|
||||
}};
|
||||
}
|
||||
|
||||
match iteratee {
|
||||
PStrIteratee::Char { value, .. } => {
|
||||
emit_char!(value);
|
||||
}
|
||||
PStrIteratee::PStrSlice { slice_loc, slice_len } => {
|
||||
PStrIteratee::PStrSlice {
|
||||
slice_loc,
|
||||
slice_len,
|
||||
} => {
|
||||
let s = iter.heap.slice_to_str(slice_loc, slice_len);
|
||||
|
||||
for c in s.chars() {
|
||||
@@ -1181,10 +1189,11 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
|
||||
if max_depth == 0 {
|
||||
while let Some(iteratee) = iter.next() {
|
||||
let iter: Box<dyn Iterator<Item = char>> = match iteratee {
|
||||
PStrIteratee::Char { value: c, .. } => {
|
||||
Box::new(std::iter::once(c))
|
||||
}
|
||||
PStrIteratee::PStrSlice { slice_loc, slice_len } => {
|
||||
PStrIteratee::Char { value: c, .. } => Box::new(std::iter::once(c)),
|
||||
PStrIteratee::PStrSlice {
|
||||
slice_loc,
|
||||
slice_len,
|
||||
} => {
|
||||
let s = iter.heap.slice_to_str(slice_loc, slice_len);
|
||||
Box::new(s.chars())
|
||||
}
|
||||
@@ -1201,10 +1210,11 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
|
||||
|
||||
while let Some(iteratee) = iter.next() {
|
||||
let iter: Box<dyn Iterator<Item = char>> = match iteratee {
|
||||
PStrIteratee::Char { value: c, .. } => {
|
||||
Box::new(std::iter::once(c))
|
||||
}
|
||||
PStrIteratee::PStrSlice { slice_loc, slice_len } => {
|
||||
PStrIteratee::Char { value: c, .. } => Box::new(std::iter::once(c)),
|
||||
PStrIteratee::PStrSlice {
|
||||
slice_loc,
|
||||
slice_len,
|
||||
} => {
|
||||
let s = iter.heap.slice_to_str(slice_loc, slice_len);
|
||||
Box::new(s.chars())
|
||||
}
|
||||
@@ -1583,22 +1593,8 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
|
||||
self.state_stack.push(TokenOrRedirect::Atom(atom!("...")));
|
||||
self.state_stack.push(TokenOrRedirect::HeadTailSeparator);
|
||||
} else {
|
||||
/*
|
||||
let end_cell_h = Heap::neighboring_cell_offset(pstr_loc);
|
||||
let end_cell = self.iter.heap[end_cell_h];
|
||||
let end_cell = heap_bound_store(
|
||||
self.iter.heap,
|
||||
heap_bound_deref(self.iter.heap, end_cell),
|
||||
);
|
||||
|
||||
if end_cell != empty_list_as_cell!() {
|
||||
self.iter.push_stack(
|
||||
IterStackLoc::iterable_loc(end_cell_h, HeapOrStackTag::Heap),
|
||||
);
|
||||
}
|
||||
*/
|
||||
|
||||
self.state_stack.push(TokenOrRedirect::FunctorRedirect(max_depth + 1));
|
||||
self.state_stack
|
||||
.push(TokenOrRedirect::FunctorRedirect(max_depth + 1));
|
||||
self.state_stack.push(TokenOrRedirect::HeadTailSeparator);
|
||||
}
|
||||
}
|
||||
@@ -1872,9 +1868,8 @@ mod tests {
|
||||
|
||||
let mut functor_writer = Heap::functor_writer(functor!(
|
||||
f_atom,
|
||||
[atom_as_cell(a_atom),
|
||||
atom_as_cell(b_atom)]),
|
||||
);
|
||||
[atom_as_cell(a_atom), atom_as_cell(b_atom)]
|
||||
));
|
||||
|
||||
let cell = functor_writer(&mut wam.machine_st.heap).unwrap();
|
||||
wam.machine_st.heap.push_cell(cell).unwrap();
|
||||
@@ -1893,7 +1888,7 @@ mod tests {
|
||||
assert_eq!(output.result(), "f(a,b)");
|
||||
}
|
||||
|
||||
all_cells_unmarked(wam.machine_st.heap.splice(..));
|
||||
all_cells_unmarked(&wam.machine_st.heap);
|
||||
|
||||
wam.machine_st.heap.clear();
|
||||
|
||||
@@ -1925,7 +1920,7 @@ mod tests {
|
||||
assert_eq!(output.result(), "f(a,b,a,...)");
|
||||
}
|
||||
|
||||
all_cells_unmarked(wam.machine_st.heap.splice(..));
|
||||
all_cells_unmarked(&wam.machine_st.heap);
|
||||
|
||||
wam.machine_st.heap.clear();
|
||||
|
||||
@@ -1968,7 +1963,7 @@ mod tests {
|
||||
assert_eq!(output.result(), "[L|L]");
|
||||
}
|
||||
|
||||
all_cells_unmarked(wam.machine_st.heap.splice(..));
|
||||
all_cells_unmarked(&wam.machine_st.heap);
|
||||
|
||||
wam.machine_st.heap.clear();
|
||||
|
||||
@@ -1984,9 +1979,11 @@ mod tests {
|
||||
|
||||
let mut functor_writer = Heap::functor_writer(functor!(
|
||||
f_atom,
|
||||
[atom_as_cell(a_atom),
|
||||
atom_as_cell(b_atom),
|
||||
atom_as_cell(b_atom)]
|
||||
[
|
||||
atom_as_cell(a_atom),
|
||||
atom_as_cell(b_atom),
|
||||
atom_as_cell(b_atom)
|
||||
]
|
||||
));
|
||||
|
||||
functor_writer(&mut wam.machine_st.heap).unwrap();
|
||||
@@ -2005,7 +2002,7 @@ mod tests {
|
||||
assert_eq!(output.result(), "[f(a,b,b),f(a,b,b)]");
|
||||
}
|
||||
|
||||
all_cells_unmarked(wam.machine_st.heap.splice(..));
|
||||
all_cells_unmarked(&wam.machine_st.heap);
|
||||
|
||||
wam.machine_st.heap[4] = list_loc_as_cell!(1);
|
||||
|
||||
@@ -2023,7 +2020,7 @@ mod tests {
|
||||
assert_eq!(output.result(), "[f(a,b,b),f(a,b,b)|...]");
|
||||
}
|
||||
|
||||
all_cells_unmarked(wam.machine_st.heap.splice(..));
|
||||
all_cells_unmarked(&wam.machine_st.heap);
|
||||
|
||||
{
|
||||
let mut printer = HCPrinter::new(
|
||||
@@ -2043,7 +2040,7 @@ mod tests {
|
||||
assert_eq!(output.result(), "[f(a,b,b),f(a,b,b)|L]");
|
||||
}
|
||||
|
||||
all_cells_unmarked(wam.machine_st.heap.splice(..));
|
||||
all_cells_unmarked(&wam.machine_st.heap);
|
||||
|
||||
// issue #382
|
||||
wam.machine_st.heap.clear();
|
||||
@@ -2077,7 +2074,7 @@ mod tests {
|
||||
assert_eq!(output.result(), "[_1,_3,_5,_7,_9|...]");
|
||||
}
|
||||
|
||||
all_cells_unmarked(wam.machine_st.heap.splice(..));
|
||||
all_cells_unmarked(&wam.machine_st.heap);
|
||||
|
||||
wam.machine_st.heap.clear();
|
||||
|
||||
@@ -2100,7 +2097,7 @@ mod tests {
|
||||
assert_eq!(output.result(), "[a,b,c|_1]");
|
||||
}
|
||||
|
||||
all_cells_unmarked(wam.machine_st.heap.splice(..));
|
||||
all_cells_unmarked(&wam.machine_st.heap);
|
||||
|
||||
let mut writer = wam.machine_st.heap.reserve(96).unwrap();
|
||||
|
||||
@@ -2131,7 +2128,7 @@ mod tests {
|
||||
assert_eq!(output.result(), "\"abcabc\"");
|
||||
}
|
||||
|
||||
all_cells_unmarked(wam.machine_st.heap.splice(..));
|
||||
all_cells_unmarked(&wam.machine_st.heap);
|
||||
|
||||
wam.machine_st.heap.clear();
|
||||
|
||||
@@ -2140,14 +2137,14 @@ mod tests {
|
||||
"=(X,[a,b,c|X])"
|
||||
);
|
||||
|
||||
all_cells_unmarked(wam.machine_st.heap.splice(..));
|
||||
all_cells_unmarked(&wam.machine_st.heap);
|
||||
|
||||
assert_eq!(
|
||||
&wam.parse_and_print_term("[a,b,\"a\",[a,b,c]].").unwrap(),
|
||||
"[a,b,[a],[a,b,c]]"
|
||||
);
|
||||
|
||||
all_cells_unmarked(wam.machine_st.heap.splice(..));
|
||||
all_cells_unmarked(&wam.machine_st.heap);
|
||||
|
||||
assert_eq!(
|
||||
&wam.parse_and_print_term("[\"abc\",e,f,[g,e,h,Y,v|[X,Y]]].")
|
||||
@@ -2155,11 +2152,11 @@ mod tests {
|
||||
"[[a,b,c],e,f,[g,e,h,Y,v,X,Y]]"
|
||||
);
|
||||
|
||||
all_cells_unmarked(wam.machine_st.heap.splice(..));
|
||||
all_cells_unmarked(&wam.machine_st.heap);
|
||||
|
||||
assert_eq!(&wam.parse_and_print_term("f((a,b)).").unwrap(), "f((a,b))");
|
||||
|
||||
all_cells_unmarked(wam.machine_st.heap.splice(..));
|
||||
all_cells_unmarked(&wam.machine_st.heap);
|
||||
|
||||
wam.op_dir
|
||||
.insert((atom!("+"), Fixity::In), OpDesc::build_with(500, YFX));
|
||||
@@ -2171,14 +2168,14 @@ mod tests {
|
||||
"[a|[]+b]"
|
||||
);
|
||||
|
||||
all_cells_unmarked(wam.machine_st.heap.splice(..));
|
||||
all_cells_unmarked(&wam.machine_st.heap);
|
||||
|
||||
assert_eq!(
|
||||
&wam.parse_and_print_term("[a|[b|c]*d].").unwrap(),
|
||||
"[a|[b|c]*d]"
|
||||
);
|
||||
|
||||
all_cells_unmarked(wam.machine_st.heap.splice(..));
|
||||
all_cells_unmarked(&wam.machine_st.heap);
|
||||
|
||||
wam.op_dir
|
||||
.insert((atom!("fy"), Fixity::Pre), OpDesc::build_with(9, FY));
|
||||
|
||||
@@ -1110,12 +1110,11 @@ pub(crate) fn constant_key_alternatives(
|
||||
constants.push(
|
||||
Fixnum::build_with_checked(value)
|
||||
.map(|n| fixnum_as_cell!(n))
|
||||
.unwrap()
|
||||
.unwrap(),
|
||||
);
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1465,11 +1464,7 @@ impl<I: Indexer> CodeOffsets<I> {
|
||||
self.indices.lists().push_back(index);
|
||||
}
|
||||
|
||||
fn index_constant(
|
||||
&mut self,
|
||||
constant: HeapCellValue,
|
||||
index: usize,
|
||||
) -> Vec<HeapCellValue> {
|
||||
fn index_constant(&mut self, constant: HeapCellValue, index: usize) -> Vec<HeapCellValue> {
|
||||
let overlapping_constants = constant_key_alternatives(constant);
|
||||
let code = self.indices.constants().entry(constant).or_default();
|
||||
|
||||
|
||||
@@ -14,7 +14,9 @@ use std::iter::*;
|
||||
use std::ops::Deref;
|
||||
use std::vec::Vec;
|
||||
|
||||
pub(crate) trait TermIterator: Deref<Target = Heap> + Iterator<Item = HeapCellValue> {
|
||||
pub(crate) trait TermIterator:
|
||||
Deref<Target = Heap> + Iterator<Item = HeapCellValue>
|
||||
{
|
||||
fn focus(&self) -> IterStackLoc;
|
||||
fn level(&mut self) -> Level;
|
||||
}
|
||||
@@ -45,9 +47,9 @@ fn record_path(
|
||||
}
|
||||
}
|
||||
(HeapCellValueTag::Lis) => {
|
||||
root_terms.insert(root_loc);
|
||||
break;
|
||||
}
|
||||
root_terms.insert(root_loc);
|
||||
break;
|
||||
}
|
||||
_ => {
|
||||
if cell.is_ref() {
|
||||
root_terms.insert(cell.get_value() as usize);
|
||||
@@ -228,7 +230,10 @@ pub(crate) enum ClauseItem<'a> {
|
||||
FirstBranch(usize),
|
||||
NextBranch,
|
||||
BranchEnd(usize),
|
||||
Chunk { chunk_num: usize, terms: &'a VecDeque<QueryTerm> },
|
||||
Chunk {
|
||||
chunk_num: usize,
|
||||
terms: &'a VecDeque<QueryTerm>,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
@@ -271,10 +276,9 @@ impl<'a> ClauseIterator<'a> {
|
||||
|
||||
while let Some(state) = self.state_stack.pop() {
|
||||
match state {
|
||||
ClauseIteratorState::RemainingBranches(terms, focus)
|
||||
if terms.len() == focus => {
|
||||
depth += 1;
|
||||
}
|
||||
ClauseIteratorState::RemainingBranches(terms, focus) if terms.len() == focus => {
|
||||
depth += 1;
|
||||
}
|
||||
_ => {
|
||||
self.state_stack.push(state);
|
||||
break;
|
||||
@@ -292,25 +296,27 @@ impl<'a> Iterator for ClauseIterator<'a> {
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
while let Some(state) = self.state_stack.pop() {
|
||||
match state {
|
||||
ClauseIteratorState::RemainingChunks(chunks, focus)
|
||||
if focus < chunks.len() => {
|
||||
if focus + 1 < chunks.len() {
|
||||
self.state_stack
|
||||
.push(ClauseIteratorState::RemainingChunks(chunks, focus + 1));
|
||||
} else {
|
||||
self.remaining_chunks_on_stack -= 1;
|
||||
}
|
||||
ClauseIteratorState::RemainingChunks(chunks, focus) if focus < chunks.len() => {
|
||||
if focus + 1 < chunks.len() {
|
||||
self.state_stack
|
||||
.push(ClauseIteratorState::RemainingChunks(chunks, focus + 1));
|
||||
} else {
|
||||
self.remaining_chunks_on_stack -= 1;
|
||||
}
|
||||
|
||||
match &chunks[focus] {
|
||||
ChunkedTerms::Branch(branches) => {
|
||||
self.state_stack
|
||||
.push(ClauseIteratorState::RemainingBranches(branches, 0));
|
||||
}
|
||||
&ChunkedTerms::Chunk { chunk_num, ref terms } => {
|
||||
return Some(ClauseItem::Chunk { chunk_num, terms });
|
||||
}
|
||||
match &chunks[focus] {
|
||||
ChunkedTerms::Branch(branches) => {
|
||||
self.state_stack
|
||||
.push(ClauseIteratorState::RemainingBranches(branches, 0));
|
||||
}
|
||||
&ChunkedTerms::Chunk {
|
||||
chunk_num,
|
||||
ref terms,
|
||||
} => {
|
||||
return Some(ClauseItem::Chunk { chunk_num, terms });
|
||||
}
|
||||
}
|
||||
}
|
||||
ClauseIteratorState::RemainingChunks(chunks, focus) => {
|
||||
debug_assert_eq!(chunks.len(), focus);
|
||||
}
|
||||
|
||||
@@ -568,6 +568,7 @@ parse_options_list(Options, Selector, DefaultPairs, OptionValues, Stub) :-
|
||||
% maplist isn't
|
||||
% declared as a
|
||||
% meta-predicate yet
|
||||
'$debug_hook',
|
||||
catch(lists:maplist(Selector, Options, OptionPairs0),
|
||||
error(E, _),
|
||||
builtins:throw(error(E, Stub))) ->
|
||||
|
||||
@@ -1165,9 +1165,8 @@ impl MachineState {
|
||||
return Err(self.error_form(type_error, stub_gen()));
|
||||
};
|
||||
|
||||
let mut iter = stackful_post_order_iter::<NonListElider>(
|
||||
&mut self.heap, &mut self.stack, root_loc,
|
||||
);
|
||||
let mut iter =
|
||||
stackful_post_order_iter::<NonListElider>(&mut self.heap, &mut self.stack, root_loc);
|
||||
|
||||
while let Some(value) = iter.next() {
|
||||
if value.get_forwarding_bit() {
|
||||
|
||||
@@ -38,7 +38,6 @@ verify_attrs([], _, _, []).
|
||||
|
||||
|
||||
call_goals([ListOfGoalLists | ListsCubed]) :-
|
||||
'$debug_hook',
|
||||
call_goals_0(ListOfGoalLists),
|
||||
call_goals(ListsCubed).
|
||||
call_goals([]).
|
||||
|
||||
@@ -145,7 +145,9 @@ impl MachineState {
|
||||
};
|
||||
|
||||
let mut iter = stackful_preorder_iter::<NonListElider>(
|
||||
&mut self.heap, &mut self.stack, root_loc, // cell,
|
||||
&mut self.heap,
|
||||
&mut self.stack,
|
||||
root_loc, // cell,
|
||||
);
|
||||
|
||||
while let Some(value) = iter.next() {
|
||||
|
||||
@@ -2102,19 +2102,13 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
|
||||
}
|
||||
|
||||
pub(super) fn compile_and_submit(&mut self) -> Result<(), SessionError> {
|
||||
let key = match self
|
||||
.payload
|
||||
.predicates
|
||||
.first()
|
||||
.map(|term| term.focus) {
|
||||
Some(focus) => {
|
||||
clause_predicate_key(self.machine_heap(), focus)
|
||||
.ok_or(SessionError::NamelessEntry)?
|
||||
}
|
||||
None => {
|
||||
return Err(SessionError::NamelessEntry);
|
||||
}
|
||||
};
|
||||
let key = match self.payload.predicates.first().map(|term| term.focus) {
|
||||
Some(focus) => clause_predicate_key(self.machine_heap(), focus)
|
||||
.ok_or(SessionError::NamelessEntry)?,
|
||||
None => {
|
||||
return Err(SessionError::NamelessEntry);
|
||||
}
|
||||
};
|
||||
|
||||
let listing_src_file_name = self.listing_src_file_name();
|
||||
|
||||
@@ -2290,13 +2284,18 @@ impl Machine {
|
||||
term_reg: RegType,
|
||||
vars: Vec<HeapCellValue>,
|
||||
) -> Result<(), SessionError> {
|
||||
let body_cell = self.machine_st.store(self.machine_st.deref(self.machine_st[term_reg]));
|
||||
let body_cell = self
|
||||
.machine_st
|
||||
.store(self.machine_st.deref(self.machine_st[term_reg]));
|
||||
|
||||
let new_header_loc = self.machine_st.heap.cell_len();
|
||||
let arity = vars.len();
|
||||
let term_loc = self.machine_st.heap.cell_len() + 1 + arity;
|
||||
|
||||
let mut writer = self.machine_st.heap.reserve(4 + arity)
|
||||
let mut writer = self
|
||||
.machine_st
|
||||
.heap
|
||||
.reserve(4 + arity)
|
||||
.map_err(|_err_loc| ParserError::ResourceError(ParserErrorSrc::default()))?;
|
||||
|
||||
writer.write_with(move |section| {
|
||||
|
||||
@@ -1,13 +1,71 @@
|
||||
use fxhash::FxBuildHasher;
|
||||
use indexmap::IndexSet;
|
||||
|
||||
use crate::atom_table::*;
|
||||
use crate::machine::get_structure_index;
|
||||
use crate::machine::heap::*;
|
||||
use crate::machine::stack::*;
|
||||
use crate::types::*;
|
||||
|
||||
use scryer_modular_bitfield::specifiers::*;
|
||||
use scryer_modular_bitfield::*;
|
||||
|
||||
use std::collections::BTreeMap;
|
||||
use std::mem;
|
||||
use std::ops::{IndexMut, Range};
|
||||
|
||||
type Trail = Vec<(Ref, HeapCellValue)>;
|
||||
#[derive(BitfieldSpecifier, Copy, Clone, Debug)]
|
||||
#[bits = 6]
|
||||
enum TrailRefTag {
|
||||
HeapCell = 0b001011,
|
||||
StackCell = 0b001101,
|
||||
AttrVar = 0b010001,
|
||||
PStrLoc = 0b001111,
|
||||
}
|
||||
|
||||
#[bitfield]
|
||||
#[repr(u64)]
|
||||
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
|
||||
struct TrailRef {
|
||||
val: B56,
|
||||
#[allow(unused)]
|
||||
m: bool,
|
||||
#[allow(unused)]
|
||||
f: bool,
|
||||
tag: TrailRefTag,
|
||||
}
|
||||
|
||||
impl TrailRef {
|
||||
#[inline(always)]
|
||||
fn heap_cell(h: usize) -> Self {
|
||||
TrailRef::new()
|
||||
.with_tag(TrailRefTag::HeapCell)
|
||||
.with_val(h as u64)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn stack_cell(h: usize) -> Self {
|
||||
TrailRef::new()
|
||||
.with_tag(TrailRefTag::StackCell)
|
||||
.with_val(h as u64)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn attr_var(h: usize) -> Self {
|
||||
TrailRef::new()
|
||||
.with_tag(TrailRefTag::AttrVar)
|
||||
.with_val(h as u64)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn pstr_loc(h: usize) -> Self {
|
||||
TrailRef::new()
|
||||
.with_tag(TrailRefTag::PStrLoc)
|
||||
.with_val(h as u64)
|
||||
}
|
||||
}
|
||||
|
||||
type Trail = Vec<(TrailRef, HeapCellValue)>;
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub enum AttrVarPolicy {
|
||||
@@ -18,15 +76,12 @@ pub enum AttrVarPolicy {
|
||||
pub trait CopierTarget: IndexMut<usize, Output = HeapCellValue> {
|
||||
fn store(&self, value: HeapCellValue) -> HeapCellValue;
|
||||
fn deref(&self, value: HeapCellValue) -> HeapCellValue;
|
||||
// fn push_cell(&mut self, value: HeapCellValue) -> Result<(), usize>;
|
||||
fn push_attr_var_queue(&mut self, attr_var_loc: usize);
|
||||
fn stack(&mut self) -> &mut Stack;
|
||||
fn threshold(&self) -> usize;
|
||||
// returns the tail location of the pstr on success
|
||||
fn as_slice_from<'a>(&'a self, from: usize) -> Box<dyn Iterator<Item = u8> + 'a>;
|
||||
fn copy_pstr_to_threshold(&mut self, pstr_loc: usize) -> Result<usize, usize>;
|
||||
fn pstr_head_cell_index(&self, pstr_loc: usize) -> usize;
|
||||
fn pstr_at(&self, loc: usize) -> bool;
|
||||
fn next_non_pstr_cell_index(&self, loc: usize) -> usize;
|
||||
fn reserve(&mut self, num_cells: usize) -> Result<HeapWriter, usize>;
|
||||
fn copy_slice_to_end(&mut self, bounds: Range<usize>) -> Result<(), usize>;
|
||||
}
|
||||
@@ -35,14 +90,25 @@ pub(crate) fn copy_term<T: CopierTarget>(
|
||||
target: T,
|
||||
addr: HeapCellValue,
|
||||
attr_var_policy: AttrVarPolicy,
|
||||
) -> Result<(), usize> {
|
||||
) -> Result<usize, usize> {
|
||||
let mut copy_term_state = CopyTermState::new(target, attr_var_policy);
|
||||
let old_threshold = copy_term_state.target.threshold();
|
||||
|
||||
copy_term_state.copy_term_impl(addr)?;
|
||||
copy_term_state.copy_attr_var_lists()?;
|
||||
copy_term_state.unwind_trail();
|
||||
|
||||
Ok(())
|
||||
let new_threshold = copy_term_state.target.threshold();
|
||||
copy_term_state.copy_pstrs()?;
|
||||
|
||||
Ok(new_threshold - old_threshold)
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct PStrData {
|
||||
pre_old_h_tail_loc: usize,
|
||||
post_old_h_tail_loc: usize,
|
||||
post_old_h_pstr_loc_locs: IndexSet<usize, FxBuildHasher>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
@@ -53,6 +119,9 @@ struct CopyTermState<T: CopierTarget> {
|
||||
target: T,
|
||||
attr_var_policy: AttrVarPolicy,
|
||||
attr_var_list_locs: Vec<(usize, HeapCellValue)>,
|
||||
// keys of pstr_loc_locs are byte indices rounded down to the
|
||||
// nearest cell boundary
|
||||
pstr_loc_locs: BTreeMap<usize, PStrData>,
|
||||
}
|
||||
|
||||
impl<T: CopierTarget> CopyTermState<T> {
|
||||
@@ -64,6 +133,7 @@ impl<T: CopierTarget> CopyTermState<T> {
|
||||
target,
|
||||
attr_var_policy,
|
||||
attr_var_list_locs: vec![],
|
||||
pstr_loc_locs: BTreeMap::new(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -74,7 +144,7 @@ impl<T: CopierTarget> CopyTermState<T> {
|
||||
|
||||
fn trail_list_cell(&mut self, addr: usize, threshold: usize) {
|
||||
let trail_item = mem::replace(&mut self.target[addr], list_loc_as_cell!(threshold));
|
||||
self.trail.push((Ref::heap_cell(addr), trail_item));
|
||||
self.trail.push((TrailRef::heap_cell(addr), trail_item));
|
||||
}
|
||||
|
||||
fn copy_list(&mut self, addr: usize) -> Result<(), usize> {
|
||||
@@ -93,7 +163,7 @@ impl<T: CopierTarget> CopyTermState<T> {
|
||||
}
|
||||
|
||||
let threshold = self.target.threshold();
|
||||
self.target.copy_slice_to_end(addr .. addr + 2)?;
|
||||
self.target.copy_slice_to_end(addr..addr + 2)?;
|
||||
|
||||
*self.value_at_scan() = list_loc_as_cell!(threshold);
|
||||
|
||||
@@ -122,54 +192,90 @@ impl<T: CopierTarget> CopyTermState<T> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/*
|
||||
* write a null byte to the first word of a partial string to
|
||||
* flag that it has been copied followed by the copied
|
||||
* string's index in the next 7 bytes. write the bytes in big
|
||||
* endian order so that the null byte is at index 0.
|
||||
*/
|
||||
fn write_pstr_index(&mut self, head_cell_idx: usize, threshold: usize) {
|
||||
let bytes = u64::to_be_bytes(threshold as u64);
|
||||
debug_assert_eq!(bytes[0], 0);
|
||||
self.target[head_cell_idx] = HeapCellValue::from_bytes(bytes);
|
||||
}
|
||||
|
||||
fn copy_partial_string(&mut self, pstr_loc: usize) -> Result<(), usize> {
|
||||
let head_cell_idx = self.target.pstr_head_cell_index(pstr_loc);
|
||||
let head_byte_idx = heap_index!(head_cell_idx);
|
||||
let pstr_offset = pstr_loc - head_byte_idx;
|
||||
|
||||
// if a partial string has been copied previously, we
|
||||
// track it by writing a null byte to its first word, which is trailed,
|
||||
// and then the new pstr_loc in the word's remaining 7 bytes. see write_pstr_index
|
||||
// comment.
|
||||
|
||||
if self.target[head_cell_idx].into_bytes()[0] == 0u8 {
|
||||
let head_bytes = self.target[head_cell_idx].into_bytes();
|
||||
let new_pstr_loc = u64::from_be_bytes(head_bytes) as usize;
|
||||
|
||||
*self.value_at_scan() = pstr_loc_as_cell!(heap_index!(new_pstr_loc) + pstr_offset);
|
||||
self.scan += 1;
|
||||
return Ok(());
|
||||
match self.pstr_loc_locs.range_mut(..=pstr_loc).next_back() {
|
||||
Some((
|
||||
_prev_pstr_loc,
|
||||
&mut PStrData {
|
||||
pre_old_h_tail_loc,
|
||||
ref mut post_old_h_pstr_loc_locs,
|
||||
..
|
||||
},
|
||||
)) if pre_old_h_tail_loc >= cell_index!(pstr_loc) => {
|
||||
post_old_h_pstr_loc_locs.insert(self.scan);
|
||||
self.scan += 1;
|
||||
return Ok(());
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
let threshold = self.target.threshold();
|
||||
let tail_loc = self.target.copy_pstr_to_threshold(head_byte_idx)?;
|
||||
let offset = self
|
||||
.target
|
||||
.as_slice_from(pstr_loc)
|
||||
.take_while(|b| *b != 0u8)
|
||||
.count();
|
||||
|
||||
*self.value_at_scan() = pstr_loc_as_cell!(heap_index!(threshold) + pstr_offset);
|
||||
let left_pstr_boundary = cell_index!(pstr_loc + offset);
|
||||
let flag = u64::from_be_bytes(self.target[left_pstr_boundary].into_bytes());
|
||||
let pstr_loc_idx = cell_index!(pstr_loc);
|
||||
|
||||
self.trail.push((Ref::heap_cell(head_cell_idx), self.target[head_cell_idx]));
|
||||
self.write_pstr_index(head_cell_idx, threshold);
|
||||
if flag == 1 {
|
||||
if left_pstr_boundary != pstr_loc_idx {
|
||||
let mut pstr_data = self
|
||||
.pstr_loc_locs
|
||||
.remove(&heap_index!(left_pstr_boundary))
|
||||
.unwrap();
|
||||
|
||||
let tail_cell = self.target[tail_loc];
|
||||
let mut writer = self.target.reserve(1)?;
|
||||
pstr_data.post_old_h_pstr_loc_locs.insert(self.scan);
|
||||
self.pstr_loc_locs
|
||||
.insert(heap_index!(cell_index!(pstr_loc)), pstr_data);
|
||||
|
||||
writer.write_with(|section| {
|
||||
section.push_cell(tail_cell);
|
||||
});
|
||||
let old_cell = self.target[pstr_loc_idx];
|
||||
self.target[pstr_loc_idx] = HeapCellValue::from_bytes(u64::to_be_bytes(1));
|
||||
self.trail
|
||||
.push((TrailRef::pstr_loc(pstr_loc_idx), old_cell));
|
||||
} else {
|
||||
let pstr_data = self
|
||||
.pstr_loc_locs
|
||||
.get_mut(&heap_index!(left_pstr_boundary))
|
||||
.unwrap();
|
||||
pstr_data.post_old_h_pstr_loc_locs.insert(self.scan);
|
||||
}
|
||||
} else {
|
||||
let old_cell = self.target[pstr_loc_idx];
|
||||
self.target[pstr_loc_idx] = HeapCellValue::from_bytes(u64::to_be_bytes(1));
|
||||
self.trail
|
||||
.push((TrailRef::pstr_loc(pstr_loc_idx), old_cell));
|
||||
|
||||
let old_tail_idx = if (pstr_loc + offset + 1) % Heap::heap_cell_alignment() == 0 {
|
||||
cell_index!(pstr_loc + offset) + 2
|
||||
} else {
|
||||
cell_index!(pstr_loc + offset) + 1
|
||||
};
|
||||
|
||||
let tail_cell = self.target[old_tail_idx];
|
||||
|
||||
let new_tail_idx = self.target.threshold();
|
||||
let mut writer = self.target.reserve(1)?;
|
||||
|
||||
writer.write_with(|section| {
|
||||
section.push_cell(tail_cell);
|
||||
});
|
||||
|
||||
let mut post_old_h_pstr_loc_locs = IndexSet::with_hasher(FxBuildHasher::default());
|
||||
post_old_h_pstr_loc_locs.insert(self.scan);
|
||||
|
||||
let pstr_data = PStrData {
|
||||
pre_old_h_tail_loc: old_tail_idx,
|
||||
post_old_h_tail_loc: new_tail_idx,
|
||||
post_old_h_pstr_loc_locs,
|
||||
};
|
||||
|
||||
self.pstr_loc_locs
|
||||
.insert(heap_index!(pstr_loc_idx), pstr_data);
|
||||
}
|
||||
|
||||
self.scan += 1;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -210,6 +316,7 @@ impl<T: CopierTarget> CopyTermState<T> {
|
||||
});
|
||||
|
||||
debug_assert_eq!(str_cell.get_tag(), HeapCellValueTag::Str);
|
||||
|
||||
self.copy_term_impl(str_cell)?;
|
||||
list_addr = self.target[heap_loc + 1];
|
||||
|
||||
@@ -227,13 +334,13 @@ impl<T: CopierTarget> CopyTermState<T> {
|
||||
self.target[frontier] = heap_loc_as_cell!(frontier);
|
||||
self.target[h] = heap_loc_as_cell!(frontier);
|
||||
|
||||
self.trail.push((Ref::heap_cell(h), heap_loc_as_cell!(h)));
|
||||
self.trail.push((TrailRef::heap_cell(h), heap_loc_as_cell!(h)));
|
||||
}
|
||||
(HeapCellValueTag::StackVar, s) => {
|
||||
self.target[frontier] = heap_loc_as_cell!(frontier);
|
||||
self.target.stack()[s] = heap_loc_as_cell!(frontier);
|
||||
|
||||
self.trail.push((Ref::stack_cell(s), stack_loc_as_cell!(s)));
|
||||
self.trail.push((TrailRef::stack_cell(s), stack_loc_as_cell!(s)));
|
||||
}
|
||||
(HeapCellValueTag::AttrVar, h) => {
|
||||
let threshold = if let AttrVarPolicy::DeepCopy = self.attr_var_policy {
|
||||
@@ -245,10 +352,10 @@ impl<T: CopierTarget> CopyTermState<T> {
|
||||
self.target[frontier] = heap_loc_as_cell!(threshold);
|
||||
self.target[h] = heap_loc_as_cell!(threshold);
|
||||
|
||||
self.trail.push((Ref::attr_var(h), attr_var_as_cell!(h)));
|
||||
self.trail.push((TrailRef::attr_var(h), attr_var_as_cell!(h)));
|
||||
|
||||
if let AttrVarPolicy::DeepCopy = self.attr_var_policy {
|
||||
let mut writer = self.target.reserve(2).unwrap();
|
||||
let mut writer = self.target.reserve(2)?;
|
||||
|
||||
writer.write_with(|section| {
|
||||
section.push_cell(attr_var_as_cell!(threshold));
|
||||
@@ -256,7 +363,7 @@ impl<T: CopierTarget> CopyTermState<T> {
|
||||
});
|
||||
|
||||
let old_list_link = self.target[h + 1];
|
||||
self.trail.push((Ref::heap_cell(h + 1), old_list_link));
|
||||
self.trail.push((TrailRef::heap_cell(h + 1), old_list_link));
|
||||
self.target[h + 1] = heap_loc_as_cell!(threshold + 1);
|
||||
|
||||
if old_list_link.get_tag() == HeapCellValueTag::Lis {
|
||||
@@ -317,7 +424,21 @@ impl<T: CopierTarget> CopyTermState<T> {
|
||||
(HeapCellValueTag::Atom, (_name, arity)) => {
|
||||
let threshold = self.target.threshold();
|
||||
|
||||
*self.value_at_scan() = str_loc_as_cell!(threshold);
|
||||
let index_cell = self.target[addr.saturating_sub(1)];
|
||||
|
||||
*self.value_at_scan() = if get_structure_index(index_cell).is_some() {
|
||||
// copy the index pointer trailing this
|
||||
// inlined or expanded goal.
|
||||
let mut writer = self.target.reserve(1).unwrap();
|
||||
|
||||
writer.write_with(|section| {
|
||||
section.push_cell(index_cell);
|
||||
});
|
||||
|
||||
str_loc_as_cell!(threshold + 1)
|
||||
} else {
|
||||
str_loc_as_cell!(threshold)
|
||||
};
|
||||
|
||||
self.target.copy_slice_to_end(addr .. addr + 1 + arity)?;
|
||||
|
||||
@@ -326,28 +447,7 @@ impl<T: CopierTarget> CopyTermState<T> {
|
||||
str_loc_as_cell!(threshold),
|
||||
);
|
||||
|
||||
self.trail.push((Ref::heap_cell(addr), trail_item));
|
||||
/*
|
||||
self.target.push(atom_as_cell!(name, arity));
|
||||
|
||||
for i in 0..arity {
|
||||
let hcv = self.target[addr + 1 + i];
|
||||
self.target.push(hcv);
|
||||
}
|
||||
*/
|
||||
if !self.target.pstr_at(addr + 1 + arity) {
|
||||
let index_cell = self.target[addr + 1 + arity];
|
||||
|
||||
if get_structure_index(index_cell).is_some() {
|
||||
// copy the index pointer trailing this
|
||||
// inlined or expanded goal.
|
||||
let mut writer = self.target.reserve(1).unwrap();
|
||||
|
||||
writer.write_with(|section| {
|
||||
section.push_cell(index_cell);
|
||||
});
|
||||
}
|
||||
}
|
||||
self.trail.push((TrailRef::heap_cell(addr), trail_item));
|
||||
}
|
||||
(HeapCellValueTag::Str, h) => {
|
||||
*self.value_at_scan() = str_loc_as_cell!(h);
|
||||
@@ -370,11 +470,6 @@ impl<T: CopierTarget> CopyTermState<T> {
|
||||
});
|
||||
|
||||
while self.scan < self.target.threshold() {
|
||||
if self.target.pstr_at(self.scan) {
|
||||
self.scan = self.target.next_non_pstr_cell_index(self.scan);
|
||||
continue;
|
||||
}
|
||||
|
||||
let addr = *self.value_at_scan();
|
||||
|
||||
read_heap_cell!(addr,
|
||||
@@ -405,17 +500,40 @@ impl<T: CopierTarget> CopyTermState<T> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn unwind_trail(mut self) {
|
||||
for (r, value) in self.trail {
|
||||
let index = r.get_value() as usize;
|
||||
fn copy_pstrs(&mut self) -> Result<(), usize> {
|
||||
while let Some((least_pstr_loc, pstr_data)) = self.pstr_loc_locs.pop_first() {
|
||||
let threshold = heap_index!(self.target.threshold());
|
||||
|
||||
match r.get_tag() {
|
||||
RefTag::AttrVar | RefTag::HeapCell => {
|
||||
for pstr_loc_loc in pstr_data.post_old_h_pstr_loc_locs {
|
||||
let pstr_loc = self.target[pstr_loc_loc].get_value() as usize;
|
||||
self.target[pstr_loc_loc] =
|
||||
pstr_loc_as_cell!(threshold + pstr_loc - least_pstr_loc);
|
||||
}
|
||||
|
||||
self.target.copy_pstr_to_threshold(least_pstr_loc)?;
|
||||
|
||||
let mut writer = self.target.reserve(1)?;
|
||||
|
||||
writer.write_with(|section| {
|
||||
section.push_cell(heap_loc_as_cell!(pstr_data.post_old_h_tail_loc));
|
||||
});
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn unwind_trail(&mut self) {
|
||||
for (r, value) in self.trail.drain(..) {
|
||||
let index = r.val() as usize;
|
||||
|
||||
match r.tag() {
|
||||
TrailRefTag::AttrVar | TrailRefTag::HeapCell => {
|
||||
self.target[index] = value;
|
||||
self.target[index].set_mark_bit(false);
|
||||
self.target[index].set_forwarding_bit(false);
|
||||
}
|
||||
RefTag::StackCell => self.target.stack()[index] = value,
|
||||
TrailRefTag::StackCell => self.target.stack()[index] = value,
|
||||
TrailRefTag::PStrLoc => self.target[index] = value,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -438,9 +556,10 @@ mod tests {
|
||||
let a_atom = atom!("a");
|
||||
let b_atom = atom!("b");
|
||||
|
||||
let mut functor_writer = Heap::functor_writer(
|
||||
functor!(f_atom, [atom_as_cell(a_atom), atom_as_cell(b_atom)]),
|
||||
);
|
||||
let mut functor_writer = Heap::functor_writer(functor!(
|
||||
f_atom,
|
||||
[atom_as_cell(a_atom), atom_as_cell(b_atom)]
|
||||
));
|
||||
|
||||
functor_writer(&mut wam.machine_st.heap).unwrap();
|
||||
|
||||
@@ -480,29 +599,233 @@ mod tests {
|
||||
copy_term(wam, pstr_loc_as_cell!(0), AttrVarPolicy::DeepCopy).unwrap();
|
||||
}
|
||||
|
||||
assert_eq!(
|
||||
wam.machine_st.heap.slice_to_str(0, "abc ".len()),
|
||||
"abc "
|
||||
);
|
||||
assert_eq!(wam.machine_st.heap.slice_to_str(0, "abc ".len()), "abc ");
|
||||
assert_eq!(wam.machine_st.heap[1], pstr_loc_as_cell!(heap_index!(2)));
|
||||
assert_eq!(
|
||||
wam.machine_st.heap.slice_to_str(heap_index!(2), "def".len()),
|
||||
wam.machine_st
|
||||
.heap
|
||||
.slice_to_str(heap_index!(2), "def".len()),
|
||||
"def"
|
||||
);
|
||||
assert_eq!(wam.machine_st.heap[3], pstr_loc_as_cell!(0));
|
||||
|
||||
assert_eq!(wam.machine_st.heap[4], pstr_loc_as_cell!(heap_index!(5)));
|
||||
assert_eq!(wam.machine_st.heap[4], pstr_loc_as_cell!(heap_index!(7)));
|
||||
assert_eq!(wam.machine_st.heap[5], pstr_loc_as_cell!(heap_index!(9)));
|
||||
assert_eq!(wam.machine_st.heap[6], pstr_loc_as_cell!(heap_index!(7)));
|
||||
|
||||
assert_eq!(
|
||||
wam.machine_st.heap.slice_to_str(heap_index!(5), "abc ".len()),
|
||||
wam.machine_st
|
||||
.heap
|
||||
.slice_to_str(heap_index!(7), "abc ".len()),
|
||||
"abc "
|
||||
);
|
||||
assert_eq!(wam.machine_st.heap[6], pstr_loc_as_cell!(heap_index!(7)));
|
||||
assert_eq!(wam.machine_st.heap[8], heap_loc_as_cell!(5));
|
||||
assert_eq!(
|
||||
wam.machine_st.heap.slice_to_str(heap_index!(7), "def".len()),
|
||||
wam.machine_st
|
||||
.heap
|
||||
.slice_to_str(heap_index!(9), "def".len()),
|
||||
"def"
|
||||
);
|
||||
assert_eq!(wam.machine_st.heap[8], pstr_loc_as_cell!(heap_index!(5)));
|
||||
assert_eq!(wam.machine_st.heap[10], heap_loc_as_cell!(6));
|
||||
|
||||
wam.machine_st.heap.clear();
|
||||
|
||||
let mut writer = wam.machine_st.heap.reserve(4).unwrap();
|
||||
|
||||
writer.write_with(|section| {
|
||||
section.push_pstr("abc ");
|
||||
section.push_cell(pstr_loc_as_cell!(heap_index!(2) + 9));
|
||||
|
||||
section.push_pstr("defdefdefdef");
|
||||
section.push_cell(pstr_loc_as_cell!(0));
|
||||
});
|
||||
|
||||
{
|
||||
let wam = TermCopyingMockWAM { wam: &mut wam };
|
||||
copy_term(wam, pstr_loc_as_cell!(0), AttrVarPolicy::DeepCopy).unwrap();
|
||||
}
|
||||
|
||||
assert_eq!(wam.machine_st.heap.slice_to_str(0, "abc ".len()), "abc ");
|
||||
assert_eq!(
|
||||
wam.machine_st.heap[1],
|
||||
pstr_loc_as_cell!(heap_index!(2) + 9)
|
||||
);
|
||||
assert_eq!(
|
||||
wam.machine_st
|
||||
.heap
|
||||
.slice_to_str(heap_index!(2), "defdefdefdef".len()),
|
||||
"defdefdefdef"
|
||||
);
|
||||
assert_eq!(wam.machine_st.heap[4], pstr_loc_as_cell!(0));
|
||||
|
||||
assert_eq!(wam.machine_st.heap[5], pstr_loc_as_cell!(heap_index!(8)));
|
||||
assert_eq!(
|
||||
wam.machine_st.heap[6],
|
||||
pstr_loc_as_cell!(heap_index!(10) + 1)
|
||||
);
|
||||
assert_eq!(wam.machine_st.heap[7], pstr_loc_as_cell!(heap_index!(8)));
|
||||
|
||||
assert_eq!(
|
||||
wam.machine_st
|
||||
.heap
|
||||
.slice_to_str(heap_index!(8), "abc ".len()),
|
||||
"abc "
|
||||
);
|
||||
assert_eq!(wam.machine_st.heap[9], heap_loc_as_cell!(6));
|
||||
assert_eq!(
|
||||
wam.machine_st
|
||||
.heap
|
||||
.slice_to_str(heap_index!(10), "fdef".len()),
|
||||
"fdef"
|
||||
);
|
||||
assert_eq!(wam.machine_st.heap[11], heap_loc_as_cell!(7));
|
||||
|
||||
wam.machine_st.heap.clear();
|
||||
|
||||
let mut writer = wam.machine_st.heap.reserve(4).unwrap();
|
||||
|
||||
writer.write_with(|section| {
|
||||
section.push_pstr("012345678912345");
|
||||
section.push_cell(pstr_loc_as_cell!(heap_index!(0)));
|
||||
});
|
||||
|
||||
{
|
||||
let wam = TermCopyingMockWAM { wam: &mut wam };
|
||||
copy_term(wam, pstr_loc_as_cell!(0), AttrVarPolicy::DeepCopy).unwrap();
|
||||
}
|
||||
|
||||
assert_eq!(
|
||||
wam.machine_st.heap.slice_to_str(0, "012345678912345".len()),
|
||||
"012345678912345"
|
||||
);
|
||||
assert_eq!(wam.machine_st.heap[3], pstr_loc_as_cell!(heap_index!(0)));
|
||||
|
||||
assert_eq!(wam.machine_st.heap[4], pstr_loc_as_cell!(heap_index!(6)));
|
||||
|
||||
assert_eq!(
|
||||
wam.machine_st
|
||||
.heap
|
||||
.slice_to_str(heap_index!(6), "012345678912345".len()),
|
||||
"012345678912345"
|
||||
);
|
||||
assert_eq!(wam.machine_st.heap[5], pstr_loc_as_cell!(heap_index!(6)));
|
||||
|
||||
wam.machine_st.heap.clear();
|
||||
|
||||
let mut writer = wam.machine_st.heap.reserve(4).unwrap();
|
||||
|
||||
writer.write_with(|section| {
|
||||
section.push_pstr("012345678912345");
|
||||
section.push_cell(pstr_loc_as_cell!(heap_index!(0) + 9));
|
||||
});
|
||||
|
||||
{
|
||||
let wam = TermCopyingMockWAM { wam: &mut wam };
|
||||
copy_term(wam, pstr_loc_as_cell!(0), AttrVarPolicy::DeepCopy).unwrap();
|
||||
}
|
||||
|
||||
assert_eq!(
|
||||
wam.machine_st.heap.slice_to_str(0, "012345678912345".len()),
|
||||
"012345678912345"
|
||||
);
|
||||
assert_eq!(
|
||||
wam.machine_st.heap[3],
|
||||
pstr_loc_as_cell!(heap_index!(0) + 9)
|
||||
);
|
||||
|
||||
assert_eq!(wam.machine_st.heap[4], pstr_loc_as_cell!(heap_index!(6)));
|
||||
assert_eq!(
|
||||
wam.machine_st.heap[5],
|
||||
pstr_loc_as_cell!(heap_index!(6) + 9)
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
wam.machine_st
|
||||
.heap
|
||||
.slice_to_str(heap_index!(6), "012345678912345".len()),
|
||||
"012345678912345"
|
||||
);
|
||||
assert_eq!(wam.machine_st.heap[9], heap_loc_as_cell!(5));
|
||||
|
||||
wam.machine_st.heap.clear();
|
||||
|
||||
let mut writer = wam.machine_st.heap.reserve(4).unwrap();
|
||||
|
||||
writer.write_with(|section| {
|
||||
section.push_pstr("012345678912345");
|
||||
section.push_cell(pstr_loc_as_cell!(heap_index!(0) + 7));
|
||||
});
|
||||
|
||||
{
|
||||
let wam = TermCopyingMockWAM { wam: &mut wam };
|
||||
copy_term(wam, pstr_loc_as_cell!(11), AttrVarPolicy::DeepCopy).unwrap();
|
||||
}
|
||||
|
||||
assert_eq!(
|
||||
wam.machine_st.heap.slice_to_str(0, "012345678912345".len()),
|
||||
"012345678912345"
|
||||
);
|
||||
assert_eq!(
|
||||
wam.machine_st.heap[3],
|
||||
pstr_loc_as_cell!(heap_index!(0) + 7)
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
wam.machine_st.heap[4],
|
||||
pstr_loc_as_cell!(heap_index!(6) + 11)
|
||||
);
|
||||
assert_eq!(
|
||||
wam.machine_st.heap[5],
|
||||
pstr_loc_as_cell!(heap_index!(6) + 7)
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
wam.machine_st
|
||||
.heap
|
||||
.slice_to_str(heap_index!(6), "012345678912345".len()),
|
||||
"012345678912345"
|
||||
);
|
||||
assert_eq!(wam.machine_st.heap[9], heap_loc_as_cell!(5));
|
||||
|
||||
wam.machine_st.heap.clear();
|
||||
|
||||
let mut writer = wam.machine_st.heap.reserve(4).unwrap();
|
||||
|
||||
writer.write_with(|section| {
|
||||
section.push_pstr("012345678912345");
|
||||
section.push_cell(pstr_loc_as_cell!(heap_index!(0) + 12));
|
||||
});
|
||||
|
||||
{
|
||||
let wam = TermCopyingMockWAM { wam: &mut wam };
|
||||
copy_term(wam, pstr_loc_as_cell!(11), AttrVarPolicy::DeepCopy).unwrap();
|
||||
}
|
||||
|
||||
assert_eq!(
|
||||
wam.machine_st.heap.slice_to_str(0, "012345678912345".len()),
|
||||
"012345678912345"
|
||||
);
|
||||
assert_eq!(
|
||||
wam.machine_st.heap[3],
|
||||
pstr_loc_as_cell!(heap_index!(0) + 12)
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
wam.machine_st.heap[4],
|
||||
pstr_loc_as_cell!(heap_index!(6) + 3)
|
||||
);
|
||||
assert_eq!(
|
||||
wam.machine_st.heap[5],
|
||||
pstr_loc_as_cell!(heap_index!(6) + 4)
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
wam.machine_st
|
||||
.heap
|
||||
.slice_to_str(heap_index!(6), "8912345".len()),
|
||||
"8912345"
|
||||
);
|
||||
assert_eq!(wam.machine_st.heap[8], heap_loc_as_cell!(5));
|
||||
|
||||
wam.machine_st.heap.clear();
|
||||
|
||||
@@ -528,7 +851,6 @@ mod tests {
|
||||
assert_eq!(wam.machine_st.heap[2], atom_as_cell!(b_atom));
|
||||
assert_eq!(wam.machine_st.heap[3], atom_as_cell!(a_atom));
|
||||
assert_eq!(wam.machine_st.heap[4], str_loc_as_cell!(0));
|
||||
|
||||
assert_eq!(wam.machine_st.heap[5], str_loc_as_cell!(6));
|
||||
assert_eq!(wam.machine_st.heap[6], atom_as_cell!(f_atom, 4));
|
||||
assert_eq!(wam.machine_st.heap[7], atom_as_cell!(a_atom));
|
||||
|
||||
@@ -206,9 +206,9 @@ impl<'a, const STOP_AT_CYCLES: bool> CycleDetectingIter<'a, STOP_AT_CYCLES> {
|
||||
}
|
||||
HeapCellValueTag::PStrLoc => {
|
||||
let h = self.next as usize;
|
||||
let (_, last_cell_loc) = self.heap.scan_slice_to_str(h);
|
||||
let tail_idx = self.heap.scan_slice_to_str(h).tail_idx;
|
||||
|
||||
if self.heap[last_cell_loc].get_forwarding_bit() {
|
||||
if self.heap[tail_idx].get_forwarding_bit() {
|
||||
if self.cycle_detection_active() {
|
||||
self.cycle_found = true;
|
||||
return None;
|
||||
@@ -219,11 +219,11 @@ impl<'a, const STOP_AT_CYCLES: bool> CycleDetectingIter<'a, STOP_AT_CYCLES> {
|
||||
continue;
|
||||
}
|
||||
|
||||
self.heap[last_cell_loc].set_forwarding_bit(true);
|
||||
self.heap[tail_idx].set_forwarding_bit(true);
|
||||
|
||||
self.next = self.heap[last_cell_loc].get_value();
|
||||
self.heap[last_cell_loc].set_value(self.current as u64);
|
||||
self.current = last_cell_loc;
|
||||
self.next = self.heap[tail_idx].get_value();
|
||||
self.heap[tail_idx].set_value(self.current as u64);
|
||||
self.current = tail_idx;
|
||||
|
||||
return Some(pstr_loc_as_cell!(h));
|
||||
}
|
||||
|
||||
@@ -2,11 +2,11 @@ use crate::atom_table::*;
|
||||
use crate::forms::*;
|
||||
use crate::instructions::*;
|
||||
use crate::iterators::fact_iterator;
|
||||
use crate::machine::Stack;
|
||||
use crate::machine::heap::*;
|
||||
use crate::machine::loader::*;
|
||||
use crate::machine::machine_errors::CompilationError;
|
||||
use crate::machine::preprocessor::*;
|
||||
use crate::machine::Stack;
|
||||
use crate::parser::ast::*;
|
||||
use crate::parser::dashu::Rational;
|
||||
use crate::types::*;
|
||||
@@ -229,7 +229,8 @@ impl VarLocsToNums {
|
||||
}
|
||||
|
||||
pub fn get(&self, idx: VarPtrIndex) -> VarPtr {
|
||||
self.map.get(&idx)
|
||||
self.map
|
||||
.get(&idx)
|
||||
.cloned()
|
||||
.map(VarPtr::Numbered)
|
||||
.unwrap_or_else(|| VarPtr::Anon)
|
||||
@@ -260,8 +261,10 @@ impl VarData {
|
||||
|
||||
if let Some(global_cut_var_num) = global_cut_var_num {
|
||||
let term = QueryTerm::GetLevel(global_cut_var_num);
|
||||
self.records[global_cut_var_num].allocation =
|
||||
VarAlloc::Perm { reg: 0, allocation: PermVarAllocation::Pending };
|
||||
self.records[global_cut_var_num].allocation = VarAlloc::Perm {
|
||||
reg: 0,
|
||||
allocation: PermVarAllocation::Pending,
|
||||
};
|
||||
|
||||
match build_stack.front_mut() {
|
||||
Some(ChunkedTerms::Branch(_)) => {
|
||||
@@ -395,11 +398,7 @@ impl VariableClassifier {
|
||||
|
||||
let mut lvl = Level::Shallow;
|
||||
let mut stack = Stack::uninitialized();
|
||||
let mut iter = fact_iterator::<false>(
|
||||
term.heap,
|
||||
&mut stack,
|
||||
term.focus,
|
||||
);
|
||||
let mut iter = fact_iterator::<false>(term.heap, &mut stack, term.focus);
|
||||
|
||||
// second arg is true to iterate the root, which may be a variable
|
||||
while let Some(subterm) = iter.next() {
|
||||
@@ -425,8 +424,7 @@ impl VariableClassifier {
|
||||
|
||||
fn probe_body_var(&mut self, context: GenContext, var_info: VarInfo) {
|
||||
let chunk_num = context.chunk_num();
|
||||
let branch_info_v = self.branch_map.entry(var_info.var)
|
||||
.or_default();
|
||||
let branch_info_v = self.branch_map.entry(var_info.var).or_default();
|
||||
|
||||
let needs_new_branch = if let Some(last_bi) = branch_info_v.last() {
|
||||
!self.root_set.contains(&last_bi.branch_num)
|
||||
@@ -489,14 +487,10 @@ impl VariableClassifier {
|
||||
|
||||
debug_assert_eq!(value.get_tag(), HeapCellValueTag::Str);
|
||||
|
||||
for idx in str_offset + 1 ..= str_offset + arity {
|
||||
for idx in str_offset + 1..=str_offset + arity {
|
||||
let mut lvl = Level::Shallow;
|
||||
let mut stack = Stack::uninitialized();
|
||||
let mut iter = fact_iterator::<false>(
|
||||
heap,
|
||||
&mut stack,
|
||||
idx,
|
||||
);
|
||||
let mut iter = fact_iterator::<false>(heap, &mut stack, idx);
|
||||
|
||||
while let Some(subterm) = iter.next() {
|
||||
if !subterm.is_var() {
|
||||
@@ -661,13 +655,14 @@ impl VariableClassifier {
|
||||
mut term_loc,
|
||||
} => {
|
||||
// return true iff new chunk should be added.
|
||||
let update_chunk_data = |build_stack: &mut ChunkedTermVec, key: PredicateKey| {
|
||||
if ClauseType::is_inlined(key.0, key.1) {
|
||||
build_stack.try_set_chunk_at_inlined_boundary()
|
||||
} else {
|
||||
build_stack.try_set_chunk_at_call_boundary()
|
||||
}
|
||||
};
|
||||
let update_chunk_data =
|
||||
|build_stack: &mut ChunkedTermVec, key: PredicateKey| {
|
||||
if ClauseType::is_inlined(key.0, key.1) {
|
||||
build_stack.try_set_chunk_at_inlined_boundary()
|
||||
} else {
|
||||
build_stack.try_set_chunk_at_call_boundary()
|
||||
}
|
||||
};
|
||||
|
||||
macro_rules! add_chunk {
|
||||
($key:expr, $tag:expr, $term_loc:expr) => {{
|
||||
@@ -678,9 +673,10 @@ impl VariableClassifier {
|
||||
let context = build_stack.current_gen_context();
|
||||
|
||||
for (arg_c, term_loc) in
|
||||
($term_loc + 1 ..= $term_loc + $key.1).enumerate()
|
||||
($term_loc + 1..=$term_loc + $key.1).enumerate()
|
||||
{
|
||||
let mut term = FocusedHeapRefMut::from(loader.machine_heap(), term_loc);
|
||||
let mut term =
|
||||
FocusedHeapRefMut::from(loader.machine_heap(), term_loc);
|
||||
|
||||
self.probe_body_term(
|
||||
arg_c + 1,
|
||||
@@ -710,9 +706,10 @@ impl VariableClassifier {
|
||||
let context = build_stack.current_gen_context();
|
||||
|
||||
for (arg_c, term_loc) in
|
||||
($term_loc + 1 ..= $term_loc + $key.1).enumerate()
|
||||
($term_loc + 1..=$term_loc + $key.1).enumerate()
|
||||
{
|
||||
let mut term = FocusedHeapRefMut::from(loader.machine_heap(), term_loc);
|
||||
let mut term =
|
||||
FocusedHeapRefMut::from(loader.machine_heap(), term_loc);
|
||||
|
||||
self.probe_body_term(
|
||||
arg_c + 1,
|
||||
@@ -1043,8 +1040,8 @@ impl BranchMap {
|
||||
|
||||
for (var, branches) in self.iter_mut() {
|
||||
let (mut var_num, var_num_incr) = match var {
|
||||
&ClassifiedVar::InSitu { var_num} => (var_num, false),
|
||||
_ => (var_data.records.len(), true)
|
||||
&ClassifiedVar::InSitu { var_num } => (var_num, false),
|
||||
_ => (var_data.records.len(), true),
|
||||
};
|
||||
|
||||
for branch in branches.iter_mut() {
|
||||
@@ -1088,7 +1085,10 @@ impl BranchMap {
|
||||
let chunk_num = chunk.term_loc.chunk_num();
|
||||
|
||||
var_data.var_locs_to_nums.insert(
|
||||
VarPtrIndex { chunk_num, term_loc },
|
||||
VarPtrIndex {
|
||||
chunk_num,
|
||||
term_loc,
|
||||
},
|
||||
var_num,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -140,10 +140,7 @@ impl MachineState {
|
||||
let a1 = self.registers[1];
|
||||
let a2 = self.registers[2];
|
||||
|
||||
step_or_resource_error!(
|
||||
self,
|
||||
copy_term(CopyTerm::new(self), a1, attr_var_policy)
|
||||
);
|
||||
step_or_resource_error!(self, copy_term(CopyTerm::new(self), a1, attr_var_policy));
|
||||
|
||||
unify_fn!(*self, heap_loc_as_cell!(old_h), a2);
|
||||
}
|
||||
@@ -162,11 +159,7 @@ impl MachineState {
|
||||
|
||||
let heap_addr = resource_error_call_result!(
|
||||
self,
|
||||
sized_iter_to_heap_list(
|
||||
&mut self.heap,
|
||||
list.len(),
|
||||
list.into_iter(),
|
||||
)
|
||||
sized_iter_to_heap_list(&mut self.heap, list.len(), list.into_iter(),)
|
||||
);
|
||||
|
||||
let target_addr = self.registers[2];
|
||||
@@ -5155,9 +5148,8 @@ impl Machine {
|
||||
let r = self.machine_st.registers[2];
|
||||
let r = self.machine_st.store(self.machine_st.deref(r));
|
||||
|
||||
let mut writer = Heap::functor_writer(
|
||||
functor!(atom!("-"), [fixnum(n), fixnum(p)]),
|
||||
);
|
||||
let mut writer =
|
||||
Heap::functor_writer(functor!(atom!("-"), [fixnum(n), fixnum(p)]));
|
||||
|
||||
let str_cell = backtrack_on_resource_error!(
|
||||
&mut self.machine_st,
|
||||
@@ -5178,9 +5170,8 @@ impl Machine {
|
||||
let r = self.machine_st.registers[2];
|
||||
let r = self.machine_st.store(self.machine_st.deref(r));
|
||||
|
||||
let mut writer = Heap::functor_writer(
|
||||
functor!(atom!("-"), [fixnum(n), fixnum(p)]),
|
||||
);
|
||||
let mut writer =
|
||||
Heap::functor_writer(functor!(atom!("-"), [fixnum(n), fixnum(p)]));
|
||||
|
||||
let str_cell = backtrack_on_resource_error!(
|
||||
&mut self.machine_st,
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -5,22 +5,17 @@ use crate::types::*;
|
||||
|
||||
use std::alloc;
|
||||
use std::convert::TryFrom;
|
||||
use std::mem;
|
||||
use std::ops::{Bound, Index, IndexMut, Range, RangeBounds};
|
||||
use std::ptr;
|
||||
use std::sync::Once;
|
||||
|
||||
use super::MachineState;
|
||||
|
||||
use bitvec::prelude::*;
|
||||
use bitvec::slice::BitSlice;
|
||||
|
||||
const ALIGN: usize = Heap::heap_cell_alignment();
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Heap {
|
||||
inner: InnerHeap,
|
||||
pstr_vec: BitVec,
|
||||
resource_err_loc: usize,
|
||||
}
|
||||
|
||||
@@ -90,40 +85,51 @@ unsafe impl Sync for Heap {}
|
||||
|
||||
static RESOURCE_ERROR_OFFSET_INIT: Once = Once::new();
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct HeapStringScan<'a> {
|
||||
pub string: &'a str,
|
||||
pub tail_idx: usize,
|
||||
}
|
||||
|
||||
// return the string at ptr and the tail location relative to ptr.
|
||||
// pstr_vec records the location of each string cell starting at index
|
||||
// 0.
|
||||
fn scan_slice_to_str(orig_ptr: *const u8, pstr_vec: &BitSlice) -> (&str, usize) {
|
||||
unsafe {
|
||||
debug_assert_eq!(pstr_vec[0], true);
|
||||
unsafe fn scan_slice_to_str<'a>(heap_slice: &'a [u8]) -> HeapStringScan<'a> {
|
||||
let string_len = heap_slice.iter().position(|b| *b == 0u8).unwrap();
|
||||
let zero_byte_addr = heap_slice.as_ptr().add(string_len);
|
||||
let sentinel_len = pstr_sentinel_length(zero_byte_addr as usize);
|
||||
let tail_idx = cell_index!(
|
||||
(string_len + sentinel_len).next_multiple_of(ALIGN)
|
||||
+ if sentinel_len <= 1 { heap_index!(1) } else { 0 }
|
||||
);
|
||||
|
||||
let tail_cell_offset = pstr_vec[0..].first_zero().unwrap();
|
||||
let offset = (ALIGN - orig_ptr.align_offset(ALIGN)) % 8;
|
||||
let buf_len = heap_index!(tail_cell_offset) - offset;
|
||||
let slice = std::slice::from_raw_parts(orig_ptr, buf_len);
|
||||
let str_slice = &heap_slice[..string_len];
|
||||
|
||||
// skip the final buffer byte which may not be 0 depending on
|
||||
// the context, i.e. marking by an iterator. it is counted by
|
||||
// the initial 1 as part of the padding but for this reason
|
||||
// mustn't be allowed to stop the count.
|
||||
|
||||
let padding_len = 1 + slice.iter()
|
||||
.rev()
|
||||
.skip(1)
|
||||
.position(|b| *b != 0u8)
|
||||
.unwrap();
|
||||
|
||||
let s_len = slice.len() - padding_len;
|
||||
(std::str::from_utf8_unchecked(&slice[0 .. s_len]), tail_cell_offset)
|
||||
HeapStringScan {
|
||||
string: std::str::from_utf8_unchecked(str_slice),
|
||||
tail_idx,
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub(crate) enum PStrSegmentCmpResult {
|
||||
Mismatch { c1: char, c2: char },
|
||||
FirstMatch { pstr_loc1: usize, pstr_loc2: usize, l1_offset: usize },
|
||||
SecondMatch { pstr_loc1: usize, pstr_loc2: usize, l2_offset: usize },
|
||||
BothMatch { pstr_loc1: usize, pstr_loc2: usize, null_offset: usize },
|
||||
Mismatch {
|
||||
c1: char,
|
||||
c2: char,
|
||||
},
|
||||
FirstMatch {
|
||||
pstr_loc1: usize,
|
||||
pstr_loc2: usize,
|
||||
l1_offset: usize,
|
||||
},
|
||||
SecondMatch {
|
||||
pstr_loc1: usize,
|
||||
pstr_loc2: usize,
|
||||
l2_offset: usize,
|
||||
},
|
||||
BothMatch {
|
||||
pstr_loc1: usize,
|
||||
pstr_loc2: usize,
|
||||
null_offset: usize,
|
||||
},
|
||||
}
|
||||
|
||||
impl PStrSegmentCmpResult {
|
||||
@@ -132,24 +138,36 @@ impl PStrSegmentCmpResult {
|
||||
pdl: &mut Vec<HeapCellValue>,
|
||||
) -> Option<std::cmp::Ordering> {
|
||||
match self {
|
||||
PStrSegmentCmpResult::FirstMatch { pstr_loc1, pstr_loc2, l1_offset } => {
|
||||
let tail1 = Heap::neighboring_cell_offset(pstr_loc1 + l1_offset);
|
||||
PStrSegmentCmpResult::FirstMatch {
|
||||
pstr_loc1,
|
||||
pstr_loc2,
|
||||
l1_offset,
|
||||
} => {
|
||||
let tail1 = Heap::pstr_tail_idx(pstr_loc1 + l1_offset);
|
||||
let rest_of_l2 = pstr_loc_as_cell!(pstr_loc2 + l1_offset);
|
||||
|
||||
pdl.push(heap_loc_as_cell!(tail1));
|
||||
pdl.push(rest_of_l2);
|
||||
}
|
||||
PStrSegmentCmpResult::SecondMatch { pstr_loc1, pstr_loc2, l2_offset } => {
|
||||
let tail2 = Heap::neighboring_cell_offset(pstr_loc2 + l2_offset);
|
||||
PStrSegmentCmpResult::SecondMatch {
|
||||
pstr_loc1,
|
||||
pstr_loc2,
|
||||
l2_offset,
|
||||
} => {
|
||||
let tail2 = Heap::pstr_tail_idx(pstr_loc2 + l2_offset);
|
||||
let rest_of_l1 = pstr_loc_as_cell!(pstr_loc1 + l2_offset);
|
||||
|
||||
pdl.push(rest_of_l1);
|
||||
pdl.push(heap_loc_as_cell!(tail2));
|
||||
}
|
||||
PStrSegmentCmpResult::BothMatch { pstr_loc1, pstr_loc2, null_offset } => {
|
||||
PStrSegmentCmpResult::BothMatch {
|
||||
pstr_loc1,
|
||||
pstr_loc2,
|
||||
null_offset,
|
||||
} => {
|
||||
// exhaustive match
|
||||
let tail1 = Heap::neighboring_cell_offset(pstr_loc1 + null_offset);
|
||||
let tail2 = Heap::neighboring_cell_offset(pstr_loc2 + null_offset);
|
||||
let tail1 = Heap::pstr_tail_idx(pstr_loc1 + null_offset);
|
||||
let tail2 = Heap::pstr_tail_idx(pstr_loc2 + null_offset);
|
||||
|
||||
pdl.push(heap_loc_as_cell!(tail1));
|
||||
pdl.push(heap_loc_as_cell!(tail2));
|
||||
@@ -163,162 +181,18 @@ impl PStrSegmentCmpResult {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub(crate) struct HeapView<'a> {
|
||||
slice: *const u8,
|
||||
cell_offset: usize,
|
||||
slice_cell_len: usize,
|
||||
pstr_slice: &'a BitSlice,
|
||||
}
|
||||
|
||||
impl<'a> HeapView<'a> {
|
||||
/*
|
||||
pub fn get(&self, idx: usize) -> Option<HeapCellValue> {
|
||||
if idx < self.slice_cell_len {
|
||||
Some(*self.index(idx))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
fn iter_follow(&mut self) -> Option<HeapCellValue> {
|
||||
if self.slice_cell_len == 0 {
|
||||
None
|
||||
} else {
|
||||
let cell;
|
||||
|
||||
if self.pstr_slice[0] {
|
||||
cell = pstr_loc_as_cell!(heap_index!(self.cell_offset));
|
||||
let next_cell_idx = self.pstr_slice[0 ..].first_zero().unwrap();
|
||||
|
||||
unsafe { self.slice = self.slice.add(heap_index!(next_cell_idx)); }
|
||||
self.slice_cell_len -= next_cell_idx;
|
||||
self.cell_offset += next_cell_idx;
|
||||
self.pstr_slice = &self.pstr_slice[next_cell_idx ..];
|
||||
} else {
|
||||
unsafe {
|
||||
cell = ptr::read(self.slice as *mut HeapCellValue);
|
||||
self.slice = self.slice.add(heap_index!(1));
|
||||
}
|
||||
|
||||
self.cell_offset += 1;
|
||||
self.slice_cell_len -= 1;
|
||||
self.pstr_slice = &self.pstr_slice[1 ..];
|
||||
}
|
||||
|
||||
Some(cell)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Iterator for HeapView<'a> {
|
||||
type Item = HeapCellValue;
|
||||
|
||||
#[inline]
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
self.iter_follow()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Index<usize> for HeapView<'a> {
|
||||
type Output = HeapCellValue;
|
||||
|
||||
fn index(&self, idx: usize) -> &Self::Output {
|
||||
debug_assert!(idx < self.slice_cell_len);
|
||||
unsafe {
|
||||
&*(self.slice.add(heap_index!(idx)) as *const HeapCellValue)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub(crate) struct HeapViewMut<'a> {
|
||||
slice: *mut u8,
|
||||
cell_offset: usize,
|
||||
slice_cell_len: usize,
|
||||
pstr_slice: &'a BitSlice,
|
||||
}
|
||||
|
||||
impl<'a> HeapViewMut<'a> {
|
||||
fn iter_follow(&mut self) -> Option<&'a mut HeapCellValue> {
|
||||
if self.slice_cell_len == 0 {
|
||||
None
|
||||
} else {
|
||||
let cell;
|
||||
|
||||
loop {
|
||||
if self.pstr_slice[0] {
|
||||
let next_cell_idx = self.pstr_slice[0 ..].first_zero().unwrap();
|
||||
|
||||
unsafe { self.slice = self.slice.add(heap_index!(next_cell_idx)); }
|
||||
|
||||
self.slice_cell_len -= next_cell_idx;
|
||||
self.cell_offset += next_cell_idx;
|
||||
self.pstr_slice = &self.pstr_slice[next_cell_idx ..];
|
||||
} else {
|
||||
unsafe {
|
||||
cell = &mut *(self.slice as *mut HeapCellValue);
|
||||
self.slice = self.slice.add(heap_index!(1));
|
||||
}
|
||||
|
||||
self.cell_offset += 1;
|
||||
self.slice_cell_len -= 1;
|
||||
self.pstr_slice = &self.pstr_slice[1 ..];
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Some(cell)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
impl<'a> Index<usize> for HeapViewMut<'a> {
|
||||
type Output = HeapCellValue;
|
||||
|
||||
fn index(&self, idx: usize) -> &Self::Output {
|
||||
debug_assert!(idx < self.slice_cell_len);
|
||||
unsafe {
|
||||
&*(self.slice.add(heap_index!(idx)) as *const HeapCellValue)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> IndexMut<usize> for HeapViewMut<'a> {
|
||||
fn index_mut(&mut self, idx: usize) -> &mut Self::Output {
|
||||
debug_assert!(idx < self.slice_cell_len);
|
||||
unsafe {
|
||||
&mut *(self.slice.add(heap_index!(idx)) as *mut HeapCellValue)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Iterator for &'a mut HeapViewMut<'a> {
|
||||
type Item = &'a mut HeapCellValue;
|
||||
|
||||
#[inline]
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
self.iter_follow()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct PStrWriteInfo {
|
||||
pstr_loc: usize,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub(crate) struct ReservedHeapSection<'a> {
|
||||
pub(crate) struct ReservedHeapSection {
|
||||
heap_ptr: *mut u8,
|
||||
heap_cell_len: usize,
|
||||
pstr_vec: &'a mut BitVec,
|
||||
}
|
||||
|
||||
impl<'a> ReservedHeapSection<'a> {
|
||||
impl ReservedHeapSection {
|
||||
#[inline]
|
||||
pub(crate) fn cell_len(&self) -> usize {
|
||||
self.heap_cell_len
|
||||
@@ -326,16 +200,16 @@ impl<'a> ReservedHeapSection<'a> {
|
||||
|
||||
pub(crate) fn push_cell(&mut self, cell: HeapCellValue) {
|
||||
unsafe {
|
||||
ptr::write(self.heap_ptr.add(heap_index!(self.heap_cell_len)) as *mut _, cell);
|
||||
ptr::write(
|
||||
self.heap_ptr.add(heap_index!(self.heap_cell_len)) as *mut _,
|
||||
cell,
|
||||
);
|
||||
}
|
||||
self.pstr_vec.push(false);
|
||||
// self.pstr_vec.push(false);
|
||||
self.heap_cell_len += 1;
|
||||
}
|
||||
|
||||
fn push_pstr_segment(
|
||||
&mut self,
|
||||
src: &str,
|
||||
) -> usize {
|
||||
fn push_pstr_segment(&mut self, src: &str) -> usize {
|
||||
if src.is_empty() {
|
||||
return 0;
|
||||
}
|
||||
@@ -354,23 +228,30 @@ impl<'a> ReservedHeapSection<'a> {
|
||||
|
||||
let align_offset = pstr_sentinel_length(zero_region_idx);
|
||||
|
||||
ptr::write_bytes(
|
||||
self.heap_ptr.add(zero_region_idx),
|
||||
0u8,
|
||||
align_offset,
|
||||
);
|
||||
ptr::write_bytes(self.heap_ptr.add(zero_region_idx), 0u8, align_offset);
|
||||
|
||||
cells_written = if align_offset == 1 {
|
||||
ptr::write_bytes(
|
||||
self.heap_ptr.add(zero_region_idx + 1),
|
||||
0u8,
|
||||
size_of::<HeapCellValue>(),
|
||||
);
|
||||
|
||||
// ensure there are at least two bytes in the boundary
|
||||
// buffer separating the string data from the tail
|
||||
// cell
|
||||
cell_index!(src.len() + align_offset + size_of::<HeapCellValue>())
|
||||
} else {
|
||||
cell_index!(src.len() + align_offset)
|
||||
};
|
||||
|
||||
cells_written = cell_index!(src.len() + align_offset);
|
||||
self.heap_cell_len += cells_written;
|
||||
}
|
||||
|
||||
cells_written
|
||||
}
|
||||
|
||||
pub(crate) fn push_pstr(
|
||||
&mut self,
|
||||
mut src: &str,
|
||||
) -> Option<HeapCellValue> {
|
||||
pub(crate) fn push_pstr(&mut self, mut src: &str) -> Option<HeapCellValue> {
|
||||
let orig_h = self.cell_len();
|
||||
|
||||
if src.is_empty() {
|
||||
@@ -386,18 +267,14 @@ impl<'a> ReservedHeapSection<'a> {
|
||||
|
||||
loop {
|
||||
let null_char_idx = src.find('\u{0}').unwrap_or_else(|| src.len());
|
||||
|
||||
let cell_len = self.cell_len();
|
||||
let cells_written = self.push_pstr_segment(&src[0..null_char_idx]);
|
||||
let tail_idx = self.cell_len();
|
||||
|
||||
self.pstr_vec.resize(cell_len + cells_written, true);
|
||||
|
||||
if cells_written == 0 {
|
||||
return None;
|
||||
} else if null_char_idx + 1 < src.len() {
|
||||
self.push_cell(pstr_loc_as_cell!(heap_index!(tail_idx + 1)));
|
||||
src = &src[null_char_idx + 1 ..];
|
||||
src = &src[null_char_idx + 1..];
|
||||
} else {
|
||||
return Some(pstr_loc_as_cell!(heap_index!(orig_h)));
|
||||
}
|
||||
@@ -420,7 +297,12 @@ impl<'a> ReservedHeapSection<'a> {
|
||||
cursor: 0,
|
||||
}];
|
||||
|
||||
while let Some(FunctorData { functor, cell_offset, mut cursor }) = functor_stack.pop() {
|
||||
while let Some(FunctorData {
|
||||
functor,
|
||||
cell_offset,
|
||||
mut cursor,
|
||||
}) = functor_stack.pop()
|
||||
{
|
||||
while cursor < functor.len() {
|
||||
match &functor[cursor] {
|
||||
&FunctorElement::AbsoluteCell(cell) => {
|
||||
@@ -460,15 +342,13 @@ impl<'a> ReservedHeapSection<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Index<usize> for ReservedHeapSection<'a> {
|
||||
impl Index<usize> for ReservedHeapSection {
|
||||
type Output = HeapCellValue;
|
||||
|
||||
#[inline]
|
||||
fn index(&self, idx: usize) -> &Self::Output {
|
||||
debug_assert!(idx < self.heap_cell_len);
|
||||
unsafe {
|
||||
&*(self.heap_ptr.add(heap_index!(idx)) as *const HeapCellValue)
|
||||
}
|
||||
unsafe { &*(self.heap_ptr as *const HeapCellValue).add(idx) }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -489,7 +369,7 @@ fn pstr_sentinel_length(chunk_len: usize) -> usize {
|
||||
#[must_use]
|
||||
#[derive(Debug)]
|
||||
pub struct HeapWriter<'a> {
|
||||
section: ReservedHeapSection<'a>,
|
||||
section: ReservedHeapSection,
|
||||
heap_byte_len: &'a mut usize,
|
||||
}
|
||||
|
||||
@@ -504,13 +384,12 @@ impl<'a> HeapWriter<'a> {
|
||||
*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(heap_index!(
|
||||
self.section.heap_cell_len - old_section_cell_len
|
||||
))
|
||||
}
|
||||
|
||||
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)) -> usize {
|
||||
let old_section_cell_len = self.section.heap_cell_len;
|
||||
writer(&mut self.section);
|
||||
*self.heap_byte_len = heap_index!(self.section.heap_cell_len);
|
||||
@@ -522,7 +401,7 @@ impl<'a> HeapWriter<'a> {
|
||||
#[inline]
|
||||
pub(crate) fn truncate(&mut self, cell_offset: usize) {
|
||||
self.section.heap_cell_len = cell_offset;
|
||||
self.section.pstr_vec.truncate(cell_offset);
|
||||
// self.section.pstr_vec.truncate(cell_offset);
|
||||
*self.heap_byte_len = heap_index!(cell_offset);
|
||||
}
|
||||
|
||||
@@ -543,9 +422,7 @@ impl<'a> Index<usize> for HeapWriter<'a> {
|
||||
#[inline]
|
||||
fn index(&self, idx: usize) -> &Self::Output {
|
||||
debug_assert!(heap_index!(idx) < *self.heap_byte_len);
|
||||
unsafe {
|
||||
&*(self.section.heap_ptr.add(heap_index!(idx)) as *const HeapCellValue)
|
||||
}
|
||||
unsafe { &*(self.section.heap_ptr.add(heap_index!(idx)) as *const HeapCellValue) }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -553,9 +430,7 @@ impl<'a> IndexMut<usize> for HeapWriter<'a> {
|
||||
#[inline]
|
||||
fn index_mut(&mut self, idx: usize) -> &mut Self::Output {
|
||||
debug_assert!(heap_index!(idx) < *self.heap_byte_len);
|
||||
unsafe {
|
||||
&mut *(self.section.heap_ptr.add(heap_index!(idx)) as *mut HeapCellValue)
|
||||
}
|
||||
unsafe { &mut *(self.section.heap_ptr.add(heap_index!(idx)) as *mut HeapCellValue) }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -564,17 +439,29 @@ impl<'a> SizedHeap for HeapWriter<'a> {
|
||||
self.section.cell_len()
|
||||
}
|
||||
|
||||
fn scan_slice_to_str(&self, slice_loc: usize) -> (&str, usize) {
|
||||
let (s, tail_cell_offset) = scan_slice_to_str(
|
||||
unsafe { self.section.heap_ptr.add(slice_loc) },
|
||||
&self.section.pstr_vec.as_bitslice()[cell_index!(slice_loc) ..],
|
||||
);
|
||||
fn scan_slice_to_str(&self, slice_loc: usize) -> HeapStringScan {
|
||||
let HeapStringScan { string, tail_idx } = unsafe {
|
||||
let slice = std::slice::from_raw_parts(
|
||||
self.section.heap_ptr.byte_add(slice_loc),
|
||||
heap_index!(self.section.heap_cell_len) - slice_loc,
|
||||
);
|
||||
|
||||
(s, cell_index!(slice_loc) + tail_cell_offset)
|
||||
scan_slice_to_str(slice)
|
||||
};
|
||||
|
||||
HeapStringScan {
|
||||
string,
|
||||
tail_idx: cell_index!(slice_loc) + tail_idx,
|
||||
}
|
||||
}
|
||||
|
||||
fn pstr_at(&self, cell_offset: usize) -> bool {
|
||||
self.section.pstr_vec[cell_offset]
|
||||
fn as_slice(&self) -> &[u8] {
|
||||
unsafe {
|
||||
std::slice::from_raw_parts(
|
||||
self.section.heap_ptr,
|
||||
heap_index!(self.section.heap_cell_len),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -588,20 +475,23 @@ impl Heap {
|
||||
byte_len: 0,
|
||||
byte_cap: 0,
|
||||
},
|
||||
pstr_vec: bitvec![],
|
||||
resource_err_loc: 0,
|
||||
}
|
||||
}
|
||||
|
||||
// takes a heap index, returns a cell index
|
||||
#[inline]
|
||||
pub const fn pstr_tail_idx(pstr_zero_byte_loc: usize) -> usize {
|
||||
if (pstr_zero_byte_loc + 1) % Heap::heap_cell_alignment() == 0 {
|
||||
cell_index!(pstr_zero_byte_loc) + 2
|
||||
} else {
|
||||
cell_index!(pstr_zero_byte_loc) + 1
|
||||
}
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
unsafe fn grow(&mut self) -> bool {
|
||||
let result = self.inner.grow();
|
||||
|
||||
if result {
|
||||
self.pstr_vec.reserve(cell_index!(self.inner.byte_cap));
|
||||
}
|
||||
|
||||
result
|
||||
self.inner.grow()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
@@ -624,7 +514,7 @@ impl Heap {
|
||||
byte_len: 0,
|
||||
byte_cap: heap_index!(cap),
|
||||
},
|
||||
pstr_vec: bitvec![],
|
||||
// pstr_vec: bitvec![],
|
||||
resource_err_loc: 0,
|
||||
})
|
||||
}
|
||||
@@ -641,7 +531,6 @@ impl Heap {
|
||||
section = ReservedHeapSection {
|
||||
heap_ptr: self.inner.ptr,
|
||||
heap_cell_len: self.cell_len(),
|
||||
pstr_vec: &mut self.pstr_vec,
|
||||
};
|
||||
break;
|
||||
} else if !self.grow() {
|
||||
@@ -656,28 +545,42 @@ impl Heap {
|
||||
})
|
||||
}
|
||||
|
||||
pub(crate) fn last_cell_mut(&mut self) -> Option<&mut HeapCellValue> {
|
||||
if self.inner.byte_len == 0 {
|
||||
None
|
||||
} else {
|
||||
unsafe {
|
||||
Some(&mut *(self.inner.ptr.add(self.inner.byte_len - heap_index!(1))
|
||||
as *mut HeapCellValue))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn last_cell(&mut self) -> Option<HeapCellValue> {
|
||||
if self.inner.byte_len == 0 {
|
||||
None
|
||||
} else {
|
||||
unsafe {
|
||||
Some(ptr::read(self.inner.ptr.add(self.inner.byte_len - heap_index!(1))
|
||||
as *const HeapCellValue))
|
||||
Some(ptr::read(
|
||||
self.inner.ptr.add(self.inner.byte_len - heap_index!(1))
|
||||
as *const HeapCellValue,
|
||||
))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn append(&mut self, other_heap: &impl SizedHeap) -> Result<(), usize> {
|
||||
let other_len = heap_index!(other_heap.cell_len());
|
||||
|
||||
loop {
|
||||
if self.free_space() >= other_len {
|
||||
let heap_slice = unsafe {
|
||||
std::slice::from_raw_parts_mut(
|
||||
self.inner.ptr.add(self.inner.byte_len),
|
||||
other_len,
|
||||
)
|
||||
};
|
||||
|
||||
heap_slice.copy_from_slice(other_heap.as_slice());
|
||||
self.inner.byte_len += heap_index!(other_heap.cell_len());
|
||||
break;
|
||||
} else if unsafe { !self.grow() } {
|
||||
return Err(self.resource_error_offset());
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn is_empty(&self) -> bool {
|
||||
self.inner.byte_len == 0
|
||||
@@ -703,31 +606,31 @@ impl Heap {
|
||||
self.inner.byte_len = 0;
|
||||
self.inner.byte_cap = 0;
|
||||
|
||||
self.pstr_vec.clear();
|
||||
// self.pstr_vec.clear();
|
||||
}
|
||||
|
||||
pub(crate) fn append(&mut self, heap_slice: HeapView) -> Result<(), usize> {
|
||||
unsafe {
|
||||
loop {
|
||||
if self.free_space() >= heap_index!(heap_slice.slice_cell_len) {
|
||||
ptr::copy_nonoverlapping(
|
||||
heap_slice.slice,
|
||||
self.inner.ptr.add(self.inner.byte_len),
|
||||
heap_index!(heap_slice.slice_cell_len),
|
||||
);
|
||||
// pub(crate) fn append(&mut self, heap_slice: HeapView) -> Result<(), usize> {
|
||||
// unsafe {
|
||||
// loop {
|
||||
// if self.free_space() >= heap_index!(heap_slice.slice_cell_len) {
|
||||
// ptr::copy_nonoverlapping(
|
||||
// heap_slice.slice,
|
||||
// self.inner.ptr.add(self.inner.byte_len),
|
||||
// heap_index!(heap_slice.slice_cell_len),
|
||||
// );
|
||||
|
||||
self.inner.byte_len += heap_index!(heap_slice.slice_cell_len);
|
||||
self.pstr_vec.extend(heap_slice.pstr_slice.iter());
|
||||
// self.inner.byte_len += heap_index!(heap_slice.slice_cell_len);
|
||||
// // self.pstr_vec.extend(heap_slice.pstr_slice.iter());
|
||||
|
||||
break;
|
||||
} else if !self.grow() {
|
||||
return Err(self.resource_error_offset());
|
||||
}
|
||||
}
|
||||
}
|
||||
// break;
|
||||
// } else if !self.grow() {
|
||||
// return Err(self.resource_error_offset());
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
Ok(())
|
||||
}
|
||||
// Ok(())
|
||||
// }
|
||||
|
||||
pub(crate) fn store_resource_error(&mut self) {
|
||||
RESOURCE_ERROR_OFFSET_INIT.call_once(move || {
|
||||
@@ -763,11 +666,23 @@ impl Heap {
|
||||
|
||||
for ((idx, c1), c2) in str1.char_indices().zip(str2.chars()) {
|
||||
if c1 == '\u{0}' && c2 == '\u{0}' {
|
||||
return PStrSegmentCmpResult::BothMatch { pstr_loc1, pstr_loc2, null_offset: idx };
|
||||
return PStrSegmentCmpResult::BothMatch {
|
||||
pstr_loc1,
|
||||
pstr_loc2,
|
||||
null_offset: idx,
|
||||
};
|
||||
} else if c1 == '\u{0}' {
|
||||
return PStrSegmentCmpResult::FirstMatch { pstr_loc1, pstr_loc2, l1_offset: idx };
|
||||
return PStrSegmentCmpResult::FirstMatch {
|
||||
pstr_loc1,
|
||||
pstr_loc2,
|
||||
l1_offset: idx,
|
||||
};
|
||||
} else if c2 == '\u{0}' {
|
||||
return PStrSegmentCmpResult::SecondMatch { pstr_loc1, pstr_loc2, l2_offset: idx };
|
||||
return PStrSegmentCmpResult::SecondMatch {
|
||||
pstr_loc1,
|
||||
pstr_loc2,
|
||||
l2_offset: idx,
|
||||
};
|
||||
} else if c1 != c2 {
|
||||
return PStrSegmentCmpResult::Mismatch { c1, c2 };
|
||||
}
|
||||
@@ -822,7 +737,7 @@ impl Heap {
|
||||
// - Invariant: from `InnerHeap`, `self.inner.byte_cap < isize::MAX`.
|
||||
let cell_ptr = (self.inner.ptr as *mut HeapCellValue).add(self.cell_len());
|
||||
cell_ptr.write(cell);
|
||||
self.pstr_vec.push(false);
|
||||
// self.pstr_vec.push(false);
|
||||
self.inner.byte_len += heap_index!(1);
|
||||
}
|
||||
|
||||
@@ -866,6 +781,7 @@ impl Heap {
|
||||
Range { start, end }
|
||||
}
|
||||
|
||||
/*
|
||||
pub(crate) fn splice<R: RangeBounds<usize>>(
|
||||
&self,
|
||||
range: R,
|
||||
@@ -876,7 +792,7 @@ impl Heap {
|
||||
slice: unsafe { self.inner.ptr.add(heap_index!(range.start)) },
|
||||
cell_offset: range.start,
|
||||
slice_cell_len: range.end - range.start,
|
||||
pstr_slice: &self.pstr_vec.as_bitslice()[range],
|
||||
// pstr_slice: &self.pstr_vec.as_bitslice()[range],
|
||||
}
|
||||
}
|
||||
|
||||
@@ -890,9 +806,10 @@ impl Heap {
|
||||
slice: unsafe { self.inner.ptr.add(heap_index!(range.start)) },
|
||||
cell_offset: range.start,
|
||||
slice_cell_len: range.end - range.start,
|
||||
pstr_slice: &self.pstr_vec.as_bitslice()[range],
|
||||
// pstr_slice: &self.pstr_vec.as_bitslice()[range],
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
pub fn allocate_pstr(&mut self, src: &str) -> Result<Option<PStrWriteInfo>, usize> {
|
||||
let size_in_heap = Self::compute_pstr_size(src);
|
||||
@@ -911,39 +828,18 @@ impl Heap {
|
||||
})
|
||||
}
|
||||
|
||||
const fn heap_cell_alignment() -> usize {
|
||||
pub const fn heap_cell_alignment() -> usize {
|
||||
// yes, size_of, not align_of. the alignment of HeapCellValue
|
||||
// is 1 byte. In the heap, though, its alignment must be its
|
||||
// size.
|
||||
mem::size_of::<HeapCellValue>()
|
||||
}
|
||||
|
||||
// takes a byte offset into the Heap ptr.
|
||||
#[inline(always)]
|
||||
pub(crate) const fn neighboring_cell_offset(offset: usize) -> usize {
|
||||
cell_index!((offset & !(ALIGN - 1)) + ALIGN)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn iter(&self) -> HeapView {
|
||||
HeapView {
|
||||
slice: self.inner.ptr,
|
||||
cell_offset: 0,
|
||||
slice_cell_len: cell_index!(self.inner.byte_len),
|
||||
pstr_slice: &self.pstr_vec.as_bitslice(),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn pstr_vec(&self) -> &BitSlice<usize> {
|
||||
self.pstr_vec.as_bitslice()
|
||||
size_of::<HeapCellValue>()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn char_at(&self, byte_idx: usize) -> char {
|
||||
let s = unsafe {
|
||||
let char_ptr = self.inner.ptr.add(byte_idx);
|
||||
let slice = std::slice::from_raw_parts(char_ptr, mem::size_of::<char>());
|
||||
let slice = std::slice::from_raw_parts(char_ptr, size_of::<char>());
|
||||
std::str::from_utf8_unchecked(&slice)
|
||||
};
|
||||
|
||||
@@ -961,7 +857,7 @@ impl Heap {
|
||||
let succ_len = loc + c.len_utf8();
|
||||
|
||||
if chars_iter.next() == Some('\u{0}') {
|
||||
(c, heap_loc_as_cell!(Self::neighboring_cell_offset(succ_len)))
|
||||
(c, heap_loc_as_cell!(Self::pstr_tail_idx(succ_len)))
|
||||
} else {
|
||||
(c, pstr_loc_as_cell!(succ_len))
|
||||
}
|
||||
@@ -971,8 +867,8 @@ impl Heap {
|
||||
// copies only the string, not its tail. returns the cell index of
|
||||
// the tail location
|
||||
pub(crate) fn copy_pstr_within(&mut self, pstr_loc: usize) -> Result<usize, usize> {
|
||||
let (s, tail_loc) = self.scan_slice_to_str(pstr_loc);
|
||||
let s_len = s.len();
|
||||
let HeapStringScan { string, tail_idx } = self.scan_slice_to_str(pstr_loc);
|
||||
let s_len = string.len();
|
||||
|
||||
let align_offset = pstr_sentinel_length(s_len);
|
||||
let copy_size = s_len + align_offset;
|
||||
@@ -980,15 +876,10 @@ impl Heap {
|
||||
unsafe {
|
||||
loop {
|
||||
if self.free_space() >= copy_size {
|
||||
let slice = std::slice::from_raw_parts_mut(
|
||||
self.inner.ptr,
|
||||
self.inner.byte_len + s_len,
|
||||
);
|
||||
let slice =
|
||||
std::slice::from_raw_parts_mut(self.inner.ptr, self.inner.byte_len + s_len);
|
||||
|
||||
slice.copy_within(
|
||||
pstr_loc .. pstr_loc + s_len,
|
||||
self.inner.byte_len,
|
||||
);
|
||||
slice.copy_within(pstr_loc..pstr_loc + s_len, self.inner.byte_len);
|
||||
|
||||
ptr::write_bytes(
|
||||
self.inner.ptr.add(self.inner.byte_len + s_len),
|
||||
@@ -996,8 +887,17 @@ impl Heap {
|
||||
align_offset,
|
||||
);
|
||||
|
||||
self.inner.byte_len += copy_size;
|
||||
self.pstr_vec.resize(self.cell_len(), true);
|
||||
if align_offset == 1 {
|
||||
ptr::write_bytes(
|
||||
self.inner.ptr.add(self.inner.byte_len + copy_size),
|
||||
0u8,
|
||||
size_of::<HeapCellValue>(),
|
||||
);
|
||||
|
||||
self.inner.byte_len += copy_size + heap_index!(1);
|
||||
} else {
|
||||
self.inner.byte_len += copy_size;
|
||||
}
|
||||
|
||||
break;
|
||||
} else if !self.grow() {
|
||||
@@ -1006,7 +906,7 @@ impl Heap {
|
||||
}
|
||||
}
|
||||
|
||||
Ok(tail_loc)
|
||||
Ok(tail_idx)
|
||||
}
|
||||
|
||||
// src is a cell-indexed range.
|
||||
@@ -1023,7 +923,7 @@ impl Heap {
|
||||
heap_index!(len),
|
||||
);
|
||||
|
||||
self.pstr_vec.resize(self.cell_len() + len, false);
|
||||
// self.pstr_vec.resize(self.cell_len() + len, false);
|
||||
self.inner.byte_len += heap_index!(len);
|
||||
|
||||
break;
|
||||
@@ -1059,10 +959,14 @@ impl Heap {
|
||||
|
||||
byte_size += null_idx + pstr_sentinel_length(null_idx);
|
||||
|
||||
// each partial string must be buffered from its tail cell
|
||||
// by at least two null bytes so one of them may be used
|
||||
// to mark partial strings e.g. during iteration
|
||||
|
||||
if (null_idx + 1) % ALIGN == 0 {
|
||||
byte_size += 2 * mem::size_of::<HeapCellValue>();
|
||||
byte_size += 2 * size_of::<HeapCellValue>();
|
||||
} else {
|
||||
byte_size += mem::size_of::<HeapCellValue>();
|
||||
byte_size += size_of::<HeapCellValue>();
|
||||
}
|
||||
|
||||
if null_idx + 1 >= src.len() {
|
||||
@@ -1082,13 +986,13 @@ impl Heap {
|
||||
while idx < functor.len() {
|
||||
match &functor[idx] {
|
||||
&FunctorElement::InnerFunctor(inner_cell_size, ref _inner_functor) => {
|
||||
byte_size += inner_cell_size as usize * mem::size_of::<HeapCellValue>();
|
||||
byte_size += inner_cell_size as usize * size_of::<HeapCellValue>();
|
||||
}
|
||||
FunctorElement::AbsoluteCell(_cell) | FunctorElement::Cell(_cell) => {
|
||||
byte_size += mem::size_of::<HeapCellValue>();
|
||||
byte_size += size_of::<HeapCellValue>();
|
||||
}
|
||||
&FunctorElement::String(cell_len, _) => {
|
||||
byte_size += cell_len as usize * mem::size_of::<HeapCellValue>();
|
||||
byte_size += cell_len as usize * size_of::<HeapCellValue>();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1120,12 +1024,10 @@ impl Heap {
|
||||
#[inline]
|
||||
pub(crate) fn truncate(&mut self, cell_offset: usize) {
|
||||
self.inner.byte_len = heap_index!(cell_offset);
|
||||
self.pstr_vec.truncate(cell_offset);
|
||||
// self.pstr_vec.truncate(cell_offset);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
pub(crate) struct PStrSegmentIter<'a> {
|
||||
string_buf: &'a str,
|
||||
}
|
||||
@@ -1153,7 +1055,7 @@ impl<'a> Iterator for PStrSegmentIter<'a> {
|
||||
if c == '\u{0}' {
|
||||
None
|
||||
} else {
|
||||
self.string_buf = &self.string_buf[c.len_utf8() ..];
|
||||
self.string_buf = &self.string_buf[c.len_utf8()..];
|
||||
Some(c)
|
||||
}
|
||||
})
|
||||
@@ -1187,14 +1089,15 @@ pub trait SizedHeap: Index<usize, Output = HeapCellValue> {
|
||||
fn cell_len(&self) -> usize;
|
||||
|
||||
// return a pointer to the heap string and the cell index of its tail
|
||||
fn scan_slice_to_str(&self, slice_loc: usize) -> (&str, usize);
|
||||
fn scan_slice_to_str<'a>(&'a self, slice_loc: usize) -> HeapStringScan<'a>;
|
||||
|
||||
fn as_slice(&self) -> &[u8];
|
||||
|
||||
// return true iff a partial string is stored at cell_offset.
|
||||
fn pstr_at(&self, cell_offset: usize) -> bool;
|
||||
// fn pstr_at(&self, cell_offset: usize) -> bool;
|
||||
}
|
||||
|
||||
pub trait SizedHeapMut: IndexMut<usize, Output = HeapCellValue> + SizedHeap {
|
||||
}
|
||||
pub trait SizedHeapMut: IndexMut<usize, Output = HeapCellValue> + SizedHeap {}
|
||||
|
||||
impl Index<usize> for Heap {
|
||||
type Output = HeapCellValue;
|
||||
@@ -1215,62 +1118,29 @@ impl SizedHeap for Heap {
|
||||
self.cell_len()
|
||||
}
|
||||
|
||||
fn scan_slice_to_str(&self, slice_loc: usize) -> (&str, usize) {
|
||||
let (s, tail_cell_offset) = scan_slice_to_str(
|
||||
unsafe { self.inner.ptr.add(slice_loc) },
|
||||
&self.pstr_vec.as_bitslice()[cell_index!(slice_loc) ..],
|
||||
);
|
||||
fn scan_slice_to_str<'a>(&'a self, slice_loc: usize) -> HeapStringScan<'a> {
|
||||
let HeapStringScan { string, tail_idx } = unsafe {
|
||||
let slice = std::slice::from_raw_parts(
|
||||
self.inner.ptr.add(slice_loc),
|
||||
self.inner.byte_len - slice_loc,
|
||||
);
|
||||
|
||||
(s, cell_index!(slice_loc) + tail_cell_offset)
|
||||
scan_slice_to_str(slice)
|
||||
};
|
||||
|
||||
HeapStringScan {
|
||||
string,
|
||||
tail_idx: cell_index!(slice_loc) + tail_idx,
|
||||
}
|
||||
}
|
||||
|
||||
fn pstr_at(&self, cell_offset: usize) -> bool {
|
||||
self.pstr_vec[cell_offset]
|
||||
fn as_slice(&self) -> &[u8] {
|
||||
unsafe { std::slice::from_raw_parts(self.inner.ptr, self.inner.byte_len) }
|
||||
}
|
||||
}
|
||||
|
||||
impl SizedHeapMut for Heap {}
|
||||
|
||||
impl<'a> SizedHeap for HeapView<'a> {
|
||||
fn cell_len(&self) -> usize {
|
||||
self.slice_cell_len
|
||||
}
|
||||
|
||||
fn scan_slice_to_str(&self, slice_loc: usize) -> (&str, usize) {
|
||||
let (s, tail_cell_offset) = scan_slice_to_str(
|
||||
unsafe { self.slice.add(slice_loc) },
|
||||
&self.pstr_slice[cell_index!(slice_loc) ..],
|
||||
);
|
||||
|
||||
(s, cell_index!(slice_loc) + tail_cell_offset)
|
||||
}
|
||||
|
||||
fn pstr_at(&self, cell_offset: usize) -> bool {
|
||||
self.pstr_slice[cell_offset]
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> SizedHeap for HeapViewMut<'a> {
|
||||
fn cell_len(&self) -> usize {
|
||||
self.slice_cell_len
|
||||
}
|
||||
|
||||
fn scan_slice_to_str(&self, slice_loc: usize) -> (&str, usize) {
|
||||
let (s, tail_cell_offset) = scan_slice_to_str(
|
||||
unsafe { self.slice.add(slice_loc) },
|
||||
&self.pstr_slice[cell_index!(slice_loc) ..],
|
||||
);
|
||||
|
||||
(s, cell_index!(slice_loc) + tail_cell_offset)
|
||||
}
|
||||
|
||||
fn pstr_at(&self, cell_offset: usize) -> bool {
|
||||
self.pstr_slice[cell_offset]
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> SizedHeapMut for HeapViewMut<'a> {}
|
||||
|
||||
// sometimes we need to dereference variables that are found only in
|
||||
// the heap without access to the full WAM (e.g., while detecting
|
||||
// cycles in terms), and which therefore may only point other cells in
|
||||
@@ -1307,9 +1177,10 @@ pub fn heap_bound_store(heap: &impl SizedHeap, value: HeapCellValue) -> HeapCell
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn print_heap_terms<'a, I: Iterator<Item = HeapCellValue>>(heap: I, h: usize) {
|
||||
for (index, term) in heap.enumerate() {
|
||||
println!("{} : {:?}", h + index, term);
|
||||
pub fn print_heap_terms(heap: &Heap, h: usize) {
|
||||
for idx in 0..heap.cell_len() {
|
||||
let term = heap[idx];
|
||||
println!("{} : {:?}", h + idx, term);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
use std::cmp::Ordering;
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
use crate::atom_table;
|
||||
@@ -442,7 +441,7 @@ impl Iterator for QueryState<'_> {
|
||||
if let Err(resource_err_loc) = machine
|
||||
.machine_st
|
||||
.heap
|
||||
.append(machine.machine_st.ball.stub.splice(..))
|
||||
.append(&machine.machine_st.ball.stub)
|
||||
{
|
||||
return Some(Err(Term::from_heapcell(
|
||||
machine,
|
||||
@@ -530,10 +529,10 @@ impl Machine {
|
||||
/// Consults a module into the [`Machine`] from a string.
|
||||
pub fn consult_module_string(&mut self, module_name: &str, program: impl Into<String>) {
|
||||
let stream = Stream::from_owned_string(program.into(), &mut self.machine_st.arena);
|
||||
self.machine_st.registers[1] = stream.into();
|
||||
self.machine_st.registers[2] = atom_as_cell!(&atom_table::AtomTable::build_with(
|
||||
self.machine_st.registers[1] = stream_as_cell!(stream);
|
||||
self.machine_st.registers[2] = atom_as_cell!(atom_table::AtomTable::build_with(
|
||||
&self.machine_st.atom_tbl,
|
||||
module_name
|
||||
module_name,
|
||||
));
|
||||
|
||||
self.run_module_predicate(atom!("loader"), (atom!("consult_stream"), 2));
|
||||
|
||||
@@ -27,15 +27,14 @@ impl TermWriteResult {
|
||||
|
||||
heap[0] = value;
|
||||
|
||||
let inverse_var_locs = inverse_var_locs_from_iter(
|
||||
stackful_preorder_iter::<NonListElider>(
|
||||
heap,
|
||||
&mut stack,
|
||||
0,
|
||||
),
|
||||
);
|
||||
let inverse_var_locs = inverse_var_locs_from_iter(stackful_preorder_iter::<NonListElider>(
|
||||
heap, &mut stack, 0,
|
||||
));
|
||||
|
||||
Ok(Self { focus, inverse_var_locs })
|
||||
Ok(Self {
|
||||
focus,
|
||||
inverse_var_locs,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -529,9 +528,10 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
|
||||
let composite_op_dir = self.wam_prelude.composite_op_dir(compilation_target);
|
||||
|
||||
let mut term = load_state.term_stream.next(&composite_op_dir)?;
|
||||
let predicate_focus_opt = load_state.predicates.first().map(|term_write_result| {
|
||||
term_write_result.focus
|
||||
});
|
||||
let predicate_focus_opt = load_state
|
||||
.predicates
|
||||
.first()
|
||||
.map(|term_write_result| term_write_result.focus);
|
||||
|
||||
let machine_st = LS::machine_st(&mut self.payload);
|
||||
let term_key_opt = clause_predicate_key(&machine_st.heap, term.focus);
|
||||
@@ -1072,10 +1072,15 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
|
||||
let cell = machine_st[r];
|
||||
|
||||
let focus = machine_st.heap.cell_len();
|
||||
machine_st.heap.push_cell(cell)
|
||||
machine_st
|
||||
.heap
|
||||
.push_cell(cell)
|
||||
.map_err(|_err_loc| ParserError::ResourceError(ParserErrorSrc::default()))?;
|
||||
|
||||
let export_list = FocusedHeapRefMut { heap: &mut machine_st.heap, focus };
|
||||
let export_list = FocusedHeapRefMut {
|
||||
heap: &mut machine_st.heap,
|
||||
focus,
|
||||
};
|
||||
let export_list = setup_module_export_list(export_list)?;
|
||||
|
||||
Ok(export_list.into_iter().collect())
|
||||
@@ -1129,8 +1134,10 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
|
||||
}
|
||||
);
|
||||
|
||||
Ok(TermWriteResult::from(&mut machine_st.heap, heap_loc_as_cell!(focus))
|
||||
.map_err(|_err_loc| ParserError::ResourceError(ParserErrorSrc::default()))?)
|
||||
Ok(
|
||||
TermWriteResult::from(&mut machine_st.heap, heap_loc_as_cell!(focus))
|
||||
.map_err(|_err_loc| ParserError::ResourceError(ParserErrorSrc::default()))?,
|
||||
)
|
||||
}
|
||||
|
||||
fn add_extensible_predicate_declaration(
|
||||
@@ -1628,18 +1635,15 @@ impl Machine {
|
||||
};
|
||||
|
||||
let value = self.machine_st.registers[2];
|
||||
let term = resource_error_call_result!(
|
||||
let term = resource_error_call_result!(
|
||||
self.machine_st,
|
||||
TermWriteResult::from(&mut self.machine_st.heap, value)
|
||||
);
|
||||
|
||||
let add_clause = || {
|
||||
let indexing_arg_opt = match term_predicate_key(&self.machine_st.heap, term.focus) {
|
||||
Some((atom!(":-"), _)) => {
|
||||
term_nth_arg(&self.machine_st.heap, term.focus, 1).and_then(|h| {
|
||||
term_nth_arg(&self.machine_st.heap, h, 1)
|
||||
})
|
||||
}
|
||||
Some((atom!(":-"), _)) => term_nth_arg(&self.machine_st.heap, term.focus, 1)
|
||||
.and_then(|h| term_nth_arg(&self.machine_st.heap, h, 1)),
|
||||
Some(_) => term_nth_arg(&self.machine_st.heap, term.focus, 1),
|
||||
None => None,
|
||||
};
|
||||
@@ -2240,9 +2244,11 @@ impl Machine {
|
||||
};
|
||||
|
||||
let mut loader = self.loader_from_heap_evacuable(temp_v!(4));
|
||||
let predicate_focus_opt = loader.payload.predicates.first().map(|term_write_result| {
|
||||
term_write_result.focus
|
||||
});
|
||||
let predicate_focus_opt = loader
|
||||
.payload
|
||||
.predicates
|
||||
.first()
|
||||
.map(|term_write_result| term_write_result.focus);
|
||||
|
||||
let is_consistent = if let Some(predicate_focus) = predicate_focus_opt {
|
||||
let machine_st = LiveLoadAndMachineState::machine_st(&mut loader.payload);
|
||||
@@ -2253,7 +2259,7 @@ impl Machine {
|
||||
|
||||
LiveLoadAndMachineState::machine_st(&mut loader.payload).fail =
|
||||
(!loader.payload.predicates.is_empty()
|
||||
&& loader.payload.predicates.compilation_target != compilation_target)
|
||||
&& loader.payload.predicates.compilation_target != compilation_target)
|
||||
|| !is_consistent;
|
||||
|
||||
let result = LiveLoadAndMachineState::evacuate(loader);
|
||||
|
||||
@@ -187,7 +187,11 @@ impl PermissionError for HeapCellValue {
|
||||
|
||||
let stub = functor!(
|
||||
atom!("permission_error"),
|
||||
[atom_as_cell((perm.as_atom())), atom_as_cell(index_atom), cell(cell)]
|
||||
[
|
||||
atom_as_cell((perm.as_atom())),
|
||||
atom_as_cell(index_atom),
|
||||
cell(cell)
|
||||
]
|
||||
);
|
||||
|
||||
MachineError {
|
||||
@@ -226,7 +230,10 @@ pub(super) trait DomainError {
|
||||
|
||||
impl DomainError for HeapCellValue {
|
||||
fn domain_error(self, _machine_st: &mut MachineState, error: DomainErrorType) -> MachineError {
|
||||
let stub = functor!(atom!("domain_error"), [atom_as_cell((error.as_atom())), cell(self)]);
|
||||
let stub = functor!(
|
||||
atom!("domain_error"),
|
||||
[atom_as_cell((error.as_atom())), cell(self)]
|
||||
);
|
||||
|
||||
MachineError {
|
||||
stub,
|
||||
@@ -239,7 +246,10 @@ impl DomainError for Number {
|
||||
fn domain_error(self, machine_st: &mut MachineState, error: DomainErrorType) -> MachineError {
|
||||
let stub = functor!(
|
||||
atom!("domain_error"),
|
||||
[atom_as_cell((error.as_atom())), number(self, (&mut machine_st.arena))]
|
||||
[
|
||||
atom_as_cell((error.as_atom())),
|
||||
number(self, (&mut machine_st.arena))
|
||||
]
|
||||
);
|
||||
|
||||
MachineError {
|
||||
@@ -280,7 +290,10 @@ impl MachineState {
|
||||
}
|
||||
|
||||
pub(super) fn evaluation_error(&mut self, eval_error: EvalError) -> MachineError {
|
||||
let stub = functor!(atom!("evaluation_error"), [atom_as_cell((eval_error.as_atom()))]);
|
||||
let stub = functor!(
|
||||
atom!("evaluation_error"),
|
||||
[atom_as_cell((eval_error.as_atom()))]
|
||||
);
|
||||
|
||||
MachineError {
|
||||
stub,
|
||||
@@ -297,7 +310,10 @@ impl MachineState {
|
||||
)
|
||||
}
|
||||
ResourceError::OutOfFiles => {
|
||||
functor!(atom!("resource_error"), [atom_as_cell((atom!("file_descriptors")))])
|
||||
functor!(
|
||||
atom!("resource_error"),
|
||||
[atom_as_cell((atom!("file_descriptors")))]
|
||||
)
|
||||
}
|
||||
};
|
||||
|
||||
@@ -480,12 +496,12 @@ impl MachineState {
|
||||
SessionError::CannotOverwriteBuiltIn(key) => self.permission_error(
|
||||
Permission::Modify,
|
||||
atom!("static_procedure"),
|
||||
functor_stub(key.0, key.1)
|
||||
functor_stub(key.0, key.1),
|
||||
),
|
||||
SessionError::CannotOverwriteStaticProcedure(key) => self.permission_error(
|
||||
Permission::Modify,
|
||||
atom!("static_procedure"),
|
||||
functor_stub(key.0, key.1)
|
||||
functor_stub(key.0, key.1),
|
||||
),
|
||||
SessionError::CannotOverwriteBuiltInModule(module) => {
|
||||
self.permission_error(Permission::Modify, atom!("static_module"), module)
|
||||
@@ -559,14 +575,14 @@ impl MachineState {
|
||||
|
||||
let stub = functor!(atom!("syntax_error"), [functor(stub)]);
|
||||
|
||||
MachineError {
|
||||
stub,
|
||||
location,
|
||||
}
|
||||
MachineError { stub, location }
|
||||
}
|
||||
|
||||
pub(super) fn representation_error(&self, flag: RepFlag) -> MachineError {
|
||||
let stub = functor!(atom!("representation_error"), [atom_as_cell((flag.as_atom()))]);
|
||||
let stub = functor!(
|
||||
atom!("representation_error"),
|
||||
[atom_as_cell((flag.as_atom()))]
|
||||
);
|
||||
|
||||
MachineError {
|
||||
stub,
|
||||
@@ -593,13 +609,19 @@ impl MachineState {
|
||||
}
|
||||
|
||||
pub(super) fn error_form(&mut self, err: MachineError, src: MachineStub) -> MachineStub {
|
||||
if let Some(ParserErrorSrc { line_num, .. }) = err.location {
|
||||
functor!(atom!("error"), [functor((err.stub)),
|
||||
functor((atom!(":")), [functor(src),
|
||||
number(line_num, (&mut self.arena))])])
|
||||
if let Some(ParserErrorSrc { line_num, .. }) = err.location {
|
||||
functor!(
|
||||
atom!("error"),
|
||||
[
|
||||
functor((err.stub)),
|
||||
functor(
|
||||
(atom!(":")),
|
||||
[functor(src), number(line_num, (&mut self.arena))]
|
||||
)
|
||||
]
|
||||
)
|
||||
} else {
|
||||
functor!(atom!("error"), [functor((err.stub)),
|
||||
functor(src)])
|
||||
functor!(atom!("error"), [functor((err.stub)), functor(src)])
|
||||
}
|
||||
}
|
||||
|
||||
@@ -826,13 +848,29 @@ impl EvalError {
|
||||
// used by '$skip_max_list'.
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub enum CycleSearchResult {
|
||||
Cyclic { lambda: usize }, // number of steps
|
||||
Cyclic {
|
||||
lambda: usize,
|
||||
}, // number of steps
|
||||
EmptyList,
|
||||
NotList { num_steps: usize, heap_loc: HeapCellValue },
|
||||
PartialList { num_steps: usize, heap_loc: HeapCellValue },
|
||||
ProperList { num_steps: usize },
|
||||
PStrLocation { num_steps: usize, pstr_loc: HeapCellValue },
|
||||
UntouchedList { num_steps: usize, list_loc: usize },
|
||||
NotList {
|
||||
num_steps: usize,
|
||||
heap_loc: HeapCellValue,
|
||||
},
|
||||
PartialList {
|
||||
num_steps: usize,
|
||||
heap_loc: HeapCellValue,
|
||||
},
|
||||
ProperList {
|
||||
num_steps: usize,
|
||||
},
|
||||
PStrLocation {
|
||||
num_steps: usize,
|
||||
pstr_loc: HeapCellValue,
|
||||
},
|
||||
UntouchedList {
|
||||
num_steps: usize,
|
||||
list_loc: usize,
|
||||
},
|
||||
}
|
||||
|
||||
impl MachineState {
|
||||
@@ -856,7 +894,9 @@ impl MachineState {
|
||||
};
|
||||
|
||||
match BrentAlgState::detect_cycles(&self.heap, sorted) {
|
||||
CycleSearchResult::NotList { .. } | CycleSearchResult::Cyclic { .. } if !sorted.is_var() => {
|
||||
CycleSearchResult::NotList { .. } | CycleSearchResult::Cyclic { .. }
|
||||
if !sorted.is_var() =>
|
||||
{
|
||||
let err = self.type_error(ValidType::List, sorted);
|
||||
Err(self.error_form(err, stub_gen()))
|
||||
}
|
||||
@@ -868,7 +908,9 @@ impl MachineState {
|
||||
let stub_gen = || functor_stub(atom!("keysort"), 2);
|
||||
|
||||
match BrentAlgState::detect_cycles(&self.heap, list) {
|
||||
CycleSearchResult::NotList { .. } | CycleSearchResult::Cyclic { .. } if !list.is_var() => {
|
||||
CycleSearchResult::NotList { .. } | CycleSearchResult::Cyclic { .. }
|
||||
if !list.is_var() =>
|
||||
{
|
||||
let err = self.type_error(ValidType::List, list);
|
||||
Err(self.error_form(err, stub_gen()))
|
||||
}
|
||||
|
||||
@@ -37,7 +37,7 @@ pub(super) enum MachineMode {
|
||||
pub(super) enum HeapPtr {
|
||||
HeapCell(usize),
|
||||
PStr(usize), // Char(usize),
|
||||
// PStrLocation(usize),
|
||||
// PStrLocation(usize),
|
||||
}
|
||||
|
||||
impl Default for HeapPtr {
|
||||
@@ -215,7 +215,8 @@ fn push_var_eq_functors(
|
||||
let mut writer = heap.reserve(1 + 5 * size)?;
|
||||
|
||||
writer.write_with(|section| {
|
||||
for (var_loc, var) in iter { // (var, binding) in iter {
|
||||
for (var_loc, var) in iter {
|
||||
// (var, binding) in iter {
|
||||
let var_atom = AtomTable::build_with(atom_tbl, &var.to_string());
|
||||
let binding = heap_loc_as_cell!(var_loc);
|
||||
|
||||
@@ -224,7 +225,7 @@ fn push_var_eq_functors(
|
||||
section.push_cell(binding);
|
||||
}
|
||||
|
||||
for idx in 0 .. size {
|
||||
for idx in 0..size {
|
||||
section.push_cell(list_loc_as_cell!(section.cell_len() + 1));
|
||||
section.push_cell(str_loc_as_cell!(src_h + 3 * idx));
|
||||
}
|
||||
@@ -252,6 +253,7 @@ pub(crate) fn copy_and_align_iter<Iter: Iterator<Item = HeapCellValue>>(
|
||||
#[derive(Debug)]
|
||||
pub struct Ball {
|
||||
pub(super) boundary: usize,
|
||||
pub(super) pstr_boundary: usize,
|
||||
pub(super) stub: Heap,
|
||||
}
|
||||
|
||||
@@ -259,12 +261,14 @@ impl Ball {
|
||||
pub(super) fn new() -> Self {
|
||||
Ball {
|
||||
boundary: 0,
|
||||
pstr_boundary: 0,
|
||||
stub: Heap::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn reset(&mut self) {
|
||||
self.boundary = 0;
|
||||
self.pstr_boundary = 0;
|
||||
self.stub.clear();
|
||||
}
|
||||
|
||||
@@ -272,10 +276,23 @@ impl Ball {
|
||||
let h = dest.cell_len();
|
||||
let diff = self.boundary as i64 - h as i64;
|
||||
|
||||
dest.append(self.stub.splice(..))?;
|
||||
let mut dest_writer = dest.reserve(self.stub.cell_len())?;
|
||||
|
||||
for cell in &mut dest.splice_mut(h ..) {
|
||||
*cell = *cell - diff;
|
||||
dest_writer.write_with(|section| {
|
||||
for idx in 0..self.pstr_boundary {
|
||||
section.push_cell(self.stub[idx] - diff);
|
||||
}
|
||||
});
|
||||
|
||||
let mut pstr_threshold = heap_index!(self.pstr_boundary);
|
||||
|
||||
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);
|
||||
});
|
||||
}
|
||||
|
||||
Ok(h)
|
||||
@@ -335,32 +352,16 @@ impl<'a> CopierTarget for CopyTerm<'a> {
|
||||
self.state.heap.cell_len()
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn as_slice_from<'b>(&'b self, from: usize) -> Box<dyn Iterator<Item = u8> + 'b> {
|
||||
Box::new(self.state.heap.as_slice()[from..].iter().cloned())
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn copy_pstr_to_threshold(&mut self, pstr_loc: usize) -> Result<usize, usize> {
|
||||
self.state.heap.copy_pstr_within(pstr_loc)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn pstr_head_cell_index(&self, pstr_loc: usize) -> usize {
|
||||
self.state.heap.pstr_vec()[0 .. cell_index!(pstr_loc)]
|
||||
.last_zero()
|
||||
.map(|idx| idx + 1)
|
||||
.unwrap_or(0)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn pstr_at(&self, loc: usize) -> bool {
|
||||
self.state.heap.pstr_vec()[loc]
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn next_non_pstr_cell_index(&self, loc: usize) -> usize {
|
||||
// unwrap is safe here because a partial string is always
|
||||
// followed by a tail cell, i.e. a non-pstr cell, supposing
|
||||
// self.state.heap[loc] is a pstr cell
|
||||
self.state.heap.pstr_vec()[loc ..].first_zero().unwrap()
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn reserve(&mut self, num_cells: usize) -> Result<HeapWriter, usize> {
|
||||
self.state.heap.reserve(num_cells)
|
||||
@@ -469,9 +470,22 @@ impl<'a> CopierTarget for CopyBallTerm<'a> {
|
||||
fn copy_pstr_to_threshold(&mut self, pstr_loc: usize) -> Result<usize, usize> {
|
||||
debug_assert!(pstr_loc < self.heap.byte_len());
|
||||
|
||||
let (string, tail_loc) = self.heap.scan_slice_to_str(pstr_loc);
|
||||
let HeapStringScan { string, tail_idx } = self.heap.scan_slice_to_str(pstr_loc);
|
||||
self.stub.allocate_pstr(string)?;
|
||||
Ok(tail_loc)
|
||||
Ok(tail_idx)
|
||||
}
|
||||
|
||||
fn as_slice_from<'b>(&'b self, from: usize) -> Box<dyn Iterator<Item = u8> + 'b> {
|
||||
if from < self.heap.byte_len() {
|
||||
Box::new(
|
||||
self.heap.as_slice()[from..]
|
||||
.iter()
|
||||
.cloned()
|
||||
.chain(self.stub.as_slice().iter().cloned()),
|
||||
)
|
||||
} else {
|
||||
Box::new(self.stub.as_slice()[from..].iter().cloned())
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
@@ -479,41 +493,6 @@ impl<'a> CopierTarget for CopyBallTerm<'a> {
|
||||
self.stub.reserve(num_cells)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn pstr_head_cell_index(&self, pstr_loc: usize) -> usize {
|
||||
if pstr_loc >= self.heap.byte_len() {
|
||||
self.stub.pstr_vec()[0 .. cell_index!(pstr_loc - self.heap.byte_len())]
|
||||
.last_zero()
|
||||
.map(|idx| idx + 1)
|
||||
.unwrap_or(0)
|
||||
} else {
|
||||
self.heap.pstr_vec()[0 .. cell_index!(pstr_loc)]
|
||||
.last_zero()
|
||||
.map(|idx| idx + 1)
|
||||
.unwrap_or(0)
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn pstr_at(&self, loc: usize) -> bool {
|
||||
if loc >= self.heap.cell_len() {
|
||||
self.stub.pstr_vec()[loc - self.heap.cell_len()]
|
||||
} else {
|
||||
self.heap.pstr_vec()[loc]
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn next_non_pstr_cell_index(&self, loc: usize) -> usize {
|
||||
let zero_from_loc = if loc >= self.heap.cell_len() {
|
||||
self.stub.pstr_vec()[loc - self.heap.cell_len() ..].first_zero().unwrap()
|
||||
} else {
|
||||
self.heap.pstr_vec()[loc ..].first_zero().unwrap()
|
||||
};
|
||||
|
||||
zero_from_loc + loc
|
||||
}
|
||||
|
||||
fn copy_slice_to_end(&mut self, bounds: Range<usize>) -> Result<(), usize> {
|
||||
let len = bounds.end - bounds.start;
|
||||
let mut stub_writer = self.stub.reserve(len)?;
|
||||
@@ -699,9 +678,9 @@ impl MachineState {
|
||||
push_var_eq_functors(
|
||||
&mut self.heap,
|
||||
var_list.len(),
|
||||
var_list.iter().map(|(var_name, var, _)| {
|
||||
(var.get_value() as usize, var_name.clone())
|
||||
}),
|
||||
var_list
|
||||
.iter()
|
||||
.map(|(var_name, var, _)| { (var.get_value() as usize, var_name.clone()) }),
|
||||
&self.atom_tbl,
|
||||
)
|
||||
);
|
||||
@@ -737,7 +716,9 @@ impl MachineState {
|
||||
|
||||
let mut singleton_var_set: IndexMap<Ref, bool> = IndexMap::new();
|
||||
|
||||
for cell in stackful_preorder_iter::<NonListElider>(&mut self.heap, &mut self.stack, term.focus) {
|
||||
for cell in
|
||||
stackful_preorder_iter::<NonListElider>(&mut self.heap, &mut self.stack, term.focus)
|
||||
{
|
||||
let cell = unmark_cell_bits!(cell);
|
||||
|
||||
if let Some(var) = cell.as_var() {
|
||||
@@ -756,9 +737,10 @@ impl MachineState {
|
||||
singleton_var_set
|
||||
.iter()
|
||||
.filter(|(var, is_singleton)| {
|
||||
**is_singleton && term.inverse_var_locs.contains_key(
|
||||
&(var.get_value() as usize)
|
||||
)
|
||||
**is_singleton
|
||||
&& term
|
||||
.inverse_var_locs
|
||||
.contains_key(&(var.get_value() as usize))
|
||||
})
|
||||
.count(),
|
||||
term.inverse_var_locs
|
||||
@@ -873,7 +855,8 @@ impl MachineState {
|
||||
CompilationError::ParserError(e) if e.is_unexpected_eof() => {
|
||||
match eof_handler(self, stream)? {
|
||||
OnEOF::Return => {
|
||||
return self.write_read_term_options(vec![], empty_list_as_cell!());
|
||||
return self
|
||||
.write_read_term_options(vec![], empty_list_as_cell!());
|
||||
}
|
||||
OnEOF::Continue => continue,
|
||||
}
|
||||
@@ -1012,11 +995,9 @@ impl MachineState {
|
||||
|
||||
let term_loc = self.heap.cell_len();
|
||||
|
||||
step_or_resource_error!(
|
||||
self,
|
||||
self.heap.push_cell(term_to_be_printed),
|
||||
{ return Ok(None); }
|
||||
);
|
||||
step_or_resource_error!(self, self.heap.push_cell(term_to_be_printed), {
|
||||
return Ok(None);
|
||||
});
|
||||
|
||||
let mut printer = HCPrinter::new(
|
||||
&mut self.heap,
|
||||
|
||||
@@ -327,9 +327,9 @@ impl MachineState {
|
||||
self.ball.reset();
|
||||
|
||||
let addr = self.registers[1];
|
||||
let ball_boundary = self.heap.cell_len();
|
||||
|
||||
step_or_resource_error!(
|
||||
self.ball.boundary = self.heap.cell_len();
|
||||
self.ball.pstr_boundary = step_or_resource_error!(
|
||||
self,
|
||||
copy_term(
|
||||
CopyBallTerm::new(
|
||||
@@ -342,8 +342,6 @@ impl MachineState {
|
||||
AttrVarPolicy::DeepCopy,
|
||||
)
|
||||
);
|
||||
|
||||
self.ball.boundary = ball_boundary;
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
@@ -359,14 +357,14 @@ impl MachineState {
|
||||
HeapPtr::PStr(h) => {
|
||||
let mut char_iter = self.heap.char_iter(h);
|
||||
|
||||
if self.s_offset == 0 { // read the car of the list
|
||||
if self.s_offset == 0 {
|
||||
// read the car of the list
|
||||
let c = char_iter.next().unwrap();
|
||||
char_as_cell!(c)
|
||||
} else { // read the (self.s_offset)^{th} cdr of the list
|
||||
let byte_offset: usize = char_iter
|
||||
.take(self.s_offset)
|
||||
.map(|c| c.len_utf8())
|
||||
.sum();
|
||||
} else {
|
||||
// read the (self.s_offset)^{th} cdr of the list
|
||||
let byte_offset: usize =
|
||||
char_iter.take(self.s_offset).map(|c| c.len_utf8()).sum();
|
||||
let new_h = h + byte_offset;
|
||||
|
||||
self.s_offset = 0;
|
||||
@@ -375,7 +373,7 @@ impl MachineState {
|
||||
self.s = HeapPtr::PStr(new_h);
|
||||
pstr_loc_as_cell!(new_h)
|
||||
} else {
|
||||
let h = Heap::neighboring_cell_offset(new_h);
|
||||
let h = Heap::pstr_tail_idx(new_h);
|
||||
self.s = HeapPtr::HeapCell(h);
|
||||
self.deref(heap_loc_as_cell!(h))
|
||||
}
|
||||
@@ -946,7 +944,7 @@ impl MachineState {
|
||||
if char_iter.next().is_some() {
|
||||
unify_fn!(*self, pstr_loc_as_cell!(pstr_loc + c.len_utf8()), a3);
|
||||
} else {
|
||||
let tail_idx = Heap::neighboring_cell_offset(pstr_loc);
|
||||
let tail_idx = Heap::pstr_tail_idx(pstr_loc);
|
||||
unify_fn!(*self, self.heap[tail_idx]);
|
||||
}
|
||||
|
||||
@@ -1044,7 +1042,12 @@ impl MachineState {
|
||||
}
|
||||
}
|
||||
|
||||
fn try_functor_fabricate_struct(&mut self, name: Atom, arity: usize, r: Ref) -> Result<(), usize> {
|
||||
fn try_functor_fabricate_struct(
|
||||
&mut self,
|
||||
name: Atom,
|
||||
arity: usize,
|
||||
r: Ref,
|
||||
) -> Result<(), usize> {
|
||||
let h = self.heap.cell_len();
|
||||
let mut writer = self.heap.reserve(arity + 1)?;
|
||||
|
||||
@@ -1144,7 +1147,7 @@ impl MachineState {
|
||||
};
|
||||
|
||||
read_heap_cell!(store_name,
|
||||
(HeapCellValueTag::Cons | HeapCellValueTag::Fixnum | // HeapCellValueTag::Char |
|
||||
(HeapCellValueTag::Cons | HeapCellValueTag::Fixnum | // HeapCellValueTag::Char |
|
||||
HeapCellValueTag::F64) if arity == 0 => {
|
||||
self.bind(a1.as_var().unwrap(), deref_name);
|
||||
}
|
||||
|
||||
@@ -51,14 +51,12 @@ impl MockWAM {
|
||||
) -> Result<String, CompilationError> {
|
||||
let term_write_result = self.parse_and_write_parsed_term_to_heap(term_string)?;
|
||||
|
||||
print_heap_terms(self.machine_st.heap.splice(..), term_write_result.focus);
|
||||
print_heap_terms(&self.machine_st.heap, term_write_result.focus);
|
||||
|
||||
let var_names = term_write_result
|
||||
.inverse_var_locs
|
||||
.iter()
|
||||
.map(|(var_loc, var_name)| {
|
||||
(self.machine_st.heap[*var_loc], var_name.clone())
|
||||
})
|
||||
.map(|(var_loc, var_name)| (self.machine_st.heap[*var_loc], var_name.clone()))
|
||||
.collect();
|
||||
|
||||
let mut printer = HCPrinter::new(
|
||||
@@ -90,6 +88,7 @@ pub struct TermCopyingMockWAM<'a> {
|
||||
impl<'a> Index<usize> for TermCopyingMockWAM<'a> {
|
||||
type Output = HeapCellValue;
|
||||
|
||||
#[inline]
|
||||
fn index(&self, index: usize) -> &HeapCellValue {
|
||||
&self.wam.machine_st.heap[index]
|
||||
}
|
||||
@@ -107,6 +106,7 @@ impl<'a> IndexMut<usize> for TermCopyingMockWAM<'a> {
|
||||
impl<'a> Deref for TermCopyingMockWAM<'a> {
|
||||
type Target = MockWAM;
|
||||
|
||||
#[inline]
|
||||
fn deref(&self) -> &Self::Target {
|
||||
self.wam
|
||||
}
|
||||
@@ -114,6 +114,7 @@ impl<'a> Deref for TermCopyingMockWAM<'a> {
|
||||
|
||||
#[cfg(test)]
|
||||
impl<'a> DerefMut for TermCopyingMockWAM<'a> {
|
||||
#[inline]
|
||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||
self.wam
|
||||
}
|
||||
@@ -170,26 +171,8 @@ impl<'a> CopierTarget for TermCopyingMockWAM<'a> {
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn pstr_head_cell_index(&self, pstr_loc: usize) -> usize {
|
||||
self.wam.machine_st.heap.pstr_vec()[0 .. cell_index!(pstr_loc)]
|
||||
.last_zero()
|
||||
.map(|idx| idx + 1)
|
||||
.unwrap_or(0)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn pstr_at(&self, loc: usize) -> bool {
|
||||
self.wam.machine_st.heap.pstr_vec()[loc]
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn next_non_pstr_cell_index(&self, loc: usize) -> usize {
|
||||
// unwrap is safe here because a partial string is always
|
||||
// followed by a tail cell, i.e. a non-pstr cell, supposing
|
||||
// self.machine_st.heap[loc] is a pstr cell
|
||||
self.wam.machine_st.heap.pstr_vec()[loc ..].first_zero()
|
||||
.map(|idx| idx + loc)
|
||||
.unwrap()
|
||||
fn as_slice_from<'b>(&'b self, from: usize) -> Box<dyn Iterator<Item = u8> + 'b> {
|
||||
Box::new(self.wam.machine_st.heap.as_slice()[from..].iter().cloned())
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
@@ -204,20 +187,9 @@ impl<'a> CopierTarget for TermCopyingMockWAM<'a> {
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
pub fn all_cells_marked_and_unforwarded(iter: impl SizedHeap) {
|
||||
let mut idx = 0;
|
||||
let cell_len = iter.cell_len();
|
||||
|
||||
while idx < cell_len {
|
||||
let curr_idx = idx;
|
||||
let cell = if iter.pstr_at(idx) {
|
||||
let (_s, last_cell_loc) = iter.scan_slice_to_str(heap_index!(idx));
|
||||
idx = last_cell_loc;
|
||||
iter[last_cell_loc - 1]
|
||||
} else {
|
||||
idx += 1;
|
||||
iter[curr_idx]
|
||||
};
|
||||
pub fn all_cells_marked_and_unforwarded(heap: &Heap, offset: usize) {
|
||||
for curr_idx in offset..heap.cell_len() {
|
||||
let cell = heap[curr_idx];
|
||||
|
||||
assert!(
|
||||
cell.get_mark_bit(),
|
||||
@@ -235,43 +207,21 @@ pub fn all_cells_marked_and_unforwarded(iter: impl SizedHeap) {
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
pub fn unmark_all_cells(mut iter: impl SizedHeapMut) {
|
||||
let mut idx = 0;
|
||||
let cell_len = iter.cell_len();
|
||||
|
||||
while idx < cell_len {
|
||||
if iter.pstr_at(idx) {
|
||||
iter[idx].set_mark_bit(false);
|
||||
|
||||
let last_cell_loc = {
|
||||
let (_s, last_cell_loc) = iter.scan_slice_to_str(heap_index!(idx));
|
||||
last_cell_loc
|
||||
};
|
||||
|
||||
iter[last_cell_loc].set_mark_bit(false);
|
||||
idx = last_cell_loc;
|
||||
} else {
|
||||
iter[idx].set_mark_bit(false);
|
||||
idx += 1;
|
||||
}
|
||||
pub fn unmark_all_cells(heap: &mut Heap, offset: usize) {
|
||||
for idx in offset..heap.cell_len() {
|
||||
heap[idx].set_mark_bit(false);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
pub fn all_cells_unmarked(iter: impl SizedHeap) {
|
||||
pub fn all_cells_unmarked(iter: &impl SizedHeap) {
|
||||
let mut idx = 0;
|
||||
let cell_len = iter.cell_len();
|
||||
|
||||
while idx < cell_len {
|
||||
let curr_idx = idx;
|
||||
let cell = if iter.pstr_at(idx) {
|
||||
let (_s, last_cell_loc) = iter.scan_slice_to_str(heap_index!(idx));
|
||||
idx = last_cell_loc;
|
||||
iter[last_cell_loc - 1]
|
||||
} else {
|
||||
idx += 1;
|
||||
iter[curr_idx]
|
||||
};
|
||||
idx += 1;
|
||||
let cell = iter[curr_idx];
|
||||
|
||||
assert!(
|
||||
!cell.get_mark_bit(),
|
||||
@@ -354,7 +304,7 @@ mod tests {
|
||||
assert!(wam.fail);
|
||||
}
|
||||
|
||||
all_cells_unmarked(wam.heap.splice(..));
|
||||
all_cells_unmarked(&wam.heap);
|
||||
|
||||
wam.fail = false;
|
||||
wam.heap.clear();
|
||||
@@ -375,7 +325,7 @@ mod tests {
|
||||
assert!(!wam.fail);
|
||||
}
|
||||
|
||||
all_cells_unmarked(wam.heap.splice(..));
|
||||
all_cells_unmarked(&wam.heap);
|
||||
|
||||
wam.fail = false;
|
||||
wam.heap.clear();
|
||||
@@ -396,7 +346,7 @@ mod tests {
|
||||
assert!(!wam.fail);
|
||||
}
|
||||
|
||||
all_cells_unmarked(wam.heap.splice(..));
|
||||
all_cells_unmarked(&wam.heap);
|
||||
|
||||
wam.fail = false;
|
||||
wam.heap.clear();
|
||||
@@ -417,7 +367,7 @@ mod tests {
|
||||
assert!(!wam.fail);
|
||||
}
|
||||
|
||||
all_cells_unmarked(wam.heap.splice(..));
|
||||
all_cells_unmarked(&wam.heap);
|
||||
|
||||
wam.fail = false;
|
||||
wam.heap.clear();
|
||||
@@ -438,7 +388,7 @@ mod tests {
|
||||
assert!(!wam.fail);
|
||||
}
|
||||
|
||||
all_cells_unmarked(wam.heap.splice(..));
|
||||
all_cells_unmarked(&wam.heap);
|
||||
|
||||
wam.fail = false;
|
||||
wam.heap.clear();
|
||||
@@ -450,7 +400,7 @@ mod tests {
|
||||
let term_write_result_2 =
|
||||
parse_and_write_parsed_term_to_heap(&mut wam, "f(A,f(A)).", &op_dir).unwrap();
|
||||
|
||||
all_cells_unmarked(wam.heap.splice(..));
|
||||
all_cells_unmarked(&wam.heap);
|
||||
|
||||
unify!(
|
||||
wam,
|
||||
@@ -461,7 +411,7 @@ mod tests {
|
||||
assert!(!wam.fail);
|
||||
}
|
||||
|
||||
all_cells_unmarked(wam.heap.splice(..));
|
||||
all_cells_unmarked(&wam.heap);
|
||||
|
||||
wam.heap.clear();
|
||||
|
||||
@@ -489,9 +439,15 @@ mod tests {
|
||||
|
||||
assert!(!wam.fail);
|
||||
|
||||
assert_eq!(wam.heap.slice_to_str(heap_index!(0), "this is a string".len()),
|
||||
"this is a string");
|
||||
assert_eq!(wam.heap[3], pstr_loc_as_cell!(heap_index!(8)));
|
||||
|
||||
all_cells_unmarked(wam.heap.splice(..));
|
||||
assert_eq!(wam.heap.slice_to_str(heap_index!(4), "this is a string".len()),
|
||||
"this is a string");
|
||||
assert_eq!(wam.heap[7], pstr_loc_as_cell!(heap_index!(8)));
|
||||
assert_eq!(wam.heap.slice_to_str(heap_index!(8), "this is a string".len()),
|
||||
"this is a string");
|
||||
assert_eq!(wam.heap[11], pstr_loc_as_cell!(heap_index!(8)));
|
||||
|
||||
wam.heap.clear();
|
||||
|
||||
@@ -515,7 +471,7 @@ mod tests {
|
||||
|
||||
assert!(!wam.fail);
|
||||
|
||||
all_cells_unmarked(wam.heap.splice(..));
|
||||
all_cells_unmarked(&wam.heap);
|
||||
|
||||
wam.heap.clear();
|
||||
|
||||
@@ -540,7 +496,7 @@ mod tests {
|
||||
assert!(wam.fail);
|
||||
|
||||
wam.fail = false;
|
||||
all_cells_unmarked(wam.heap.splice(..));
|
||||
all_cells_unmarked(&wam.heap);
|
||||
|
||||
wam.heap.clear();
|
||||
|
||||
@@ -562,7 +518,7 @@ mod tests {
|
||||
|
||||
unify!(wam, heap_loc_as_cell!(0), heap_loc_as_cell!(5));
|
||||
assert!(!wam.fail);
|
||||
all_cells_unmarked(wam.heap.splice(..));
|
||||
all_cells_unmarked(&wam.heap);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -581,7 +537,7 @@ mod tests {
|
||||
let term_write_result_2 =
|
||||
parse_and_write_parsed_term_to_heap(&mut wam, "f(A,f(A)).", &op_dir).unwrap();
|
||||
|
||||
all_cells_unmarked(wam.heap.splice(..));
|
||||
all_cells_unmarked(&wam.heap);
|
||||
|
||||
unify_with_occurs_check!(
|
||||
wam,
|
||||
@@ -632,11 +588,7 @@ mod tests {
|
||||
let cstr_cell = wam.allocate_cstr("string").unwrap();
|
||||
|
||||
assert_eq!(
|
||||
compare_term_test!(
|
||||
wam,
|
||||
atom_as_cell!(atom!("atom")),
|
||||
cstr_cell
|
||||
),
|
||||
compare_term_test!(wam, atom_as_cell!(atom!("atom")), cstr_cell),
|
||||
Some(Ordering::Less)
|
||||
);
|
||||
|
||||
@@ -735,11 +687,7 @@ mod tests {
|
||||
let cstr_cell = wam.allocate_cstr("string").unwrap();
|
||||
|
||||
assert_eq!(
|
||||
compare_term_test!(
|
||||
wam,
|
||||
empty_list_as_cell!(),
|
||||
cstr_cell
|
||||
),
|
||||
compare_term_test!(wam, empty_list_as_cell!(), cstr_cell),
|
||||
Some(Ordering::Less)
|
||||
);
|
||||
|
||||
@@ -782,16 +730,13 @@ mod tests {
|
||||
assert!(!wam.is_cyclic_term(1));
|
||||
assert!(!wam.is_cyclic_term(2));
|
||||
|
||||
all_cells_unmarked(wam.heap.splice(..));
|
||||
all_cells_unmarked(&wam.heap);
|
||||
wam.heap.clear();
|
||||
|
||||
let mut functor_writer = Heap::functor_writer(
|
||||
functor!(
|
||||
atom!("f"),
|
||||
[atom_as_cell((atom!("a"))),
|
||||
atom_as_cell((atom!("b")))]
|
||||
),
|
||||
);
|
||||
let mut functor_writer = Heap::functor_writer(functor!(
|
||||
atom!("f"),
|
||||
[atom_as_cell((atom!("a"))), atom_as_cell((atom!("b")))]
|
||||
));
|
||||
|
||||
functor_writer(&mut wam.heap).unwrap();
|
||||
|
||||
@@ -800,30 +745,30 @@ mod tests {
|
||||
|
||||
assert!(!wam.is_cyclic_term(h));
|
||||
|
||||
all_cells_unmarked(wam.heap.splice(..));
|
||||
all_cells_unmarked(&wam.heap);
|
||||
|
||||
assert!(!wam.is_cyclic_term(1));
|
||||
|
||||
all_cells_unmarked(wam.heap.splice(..));
|
||||
all_cells_unmarked(&wam.heap);
|
||||
|
||||
assert!(!wam.is_cyclic_term(2));
|
||||
|
||||
all_cells_unmarked(wam.heap.splice(..));
|
||||
all_cells_unmarked(&wam.heap);
|
||||
|
||||
wam.heap[2] = str_loc_as_cell!(0);
|
||||
|
||||
print_heap_terms(wam.heap.iter(), 0);
|
||||
print_heap_terms(&wam.heap, 0);
|
||||
|
||||
assert!(wam.is_cyclic_term(2));
|
||||
|
||||
all_cells_unmarked(wam.heap.splice(..));
|
||||
all_cells_unmarked(&wam.heap);
|
||||
|
||||
wam.heap[2] = atom_as_cell!(atom!("b"));
|
||||
wam.heap[1] = str_loc_as_cell!(0);
|
||||
|
||||
assert!(wam.is_cyclic_term(1));
|
||||
|
||||
all_cells_unmarked(wam.heap.splice(..));
|
||||
all_cells_unmarked(&wam.heap);
|
||||
|
||||
wam.heap.clear();
|
||||
|
||||
|
||||
@@ -508,7 +508,8 @@ impl Machine {
|
||||
s,
|
||||
)) => {
|
||||
cell = self.deref_register(arg);
|
||||
self.machine_st.select_switch_on_term_index(cell, v, c, l, s)
|
||||
self.machine_st
|
||||
.select_switch_on_term_index(cell, v, c, l, s)
|
||||
}
|
||||
IndexingLine::Indexing(IndexingInstruction::SwitchOnConstant(hm)) => {
|
||||
// let lit = self.machine_st.constant_to_literal(cell);
|
||||
@@ -1113,6 +1114,7 @@ impl Machine {
|
||||
if let Some(idx) = self.indices.code_dir.get(&(name, arity)).cloned() {
|
||||
self.try_execute(name, arity, idx.get())
|
||||
} else {
|
||||
println!("aaand undefined!");
|
||||
self.undefined_procedure(name, arity)
|
||||
}
|
||||
} else if let Some(module) = self.indices.modules.get(&module_name) {
|
||||
|
||||
@@ -19,9 +19,17 @@ pub struct HeapPStrIter<'a> {
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub enum PStrCmpResult<'a> {
|
||||
ListMatch { list_loc: usize },
|
||||
CompletePStrMatch { chars_matched: usize, pstr_loc: usize },
|
||||
PartialPStrMatch { string: &'a str, var_loc: usize },
|
||||
ListMatch {
|
||||
list_loc: usize,
|
||||
},
|
||||
CompletePStrMatch {
|
||||
chars_matched: usize,
|
||||
pstr_loc: usize,
|
||||
},
|
||||
PartialPStrMatch {
|
||||
string: &'a str,
|
||||
var_loc: usize,
|
||||
},
|
||||
}
|
||||
|
||||
struct PStrIterStep {
|
||||
@@ -81,7 +89,7 @@ impl<'a> HeapPStrIter<'a> {
|
||||
if s.is_empty() {
|
||||
return Some(PStrCmpResult::CompletePStrMatch { chars_matched, pstr_loc: h });
|
||||
} else {
|
||||
let next_hare = Heap::neighboring_cell_offset(h + bytes_matched);
|
||||
let next_hare = Heap::pstr_tail_idx(h + bytes_matched);
|
||||
curr_hare = next_hare;
|
||||
}
|
||||
}
|
||||
@@ -179,11 +187,11 @@ impl<'a> HeapPStrIter<'a> {
|
||||
loop {
|
||||
read_heap_cell!(self.heap[curr_hare],
|
||||
(HeapCellValueTag::PStrLoc, h) => {
|
||||
let (s, tail_loc) = self.heap.scan_slice_to_str(h);
|
||||
let HeapStringScan { string, tail_idx } = self.heap.scan_slice_to_str(h);
|
||||
|
||||
return Ok(PStrIterStep {
|
||||
iteratee: PStrIteratee::PStrSlice { slice_loc: h, slice_len: s.len() },
|
||||
next_hare: tail_loc,
|
||||
iteratee: PStrIteratee::PStrSlice { slice_loc: h, slice_len: string.len() },
|
||||
next_hare: tail_idx,
|
||||
});
|
||||
}
|
||||
(HeapCellValueTag::Lis, h) => {
|
||||
@@ -319,7 +327,10 @@ impl<'a> Iterator for PStrCharsIter<'a> {
|
||||
self.item = self.iter.next();
|
||||
return Some(value);
|
||||
}
|
||||
PStrIteratee::PStrSlice { slice_loc, slice_len } => {
|
||||
PStrIteratee::PStrSlice {
|
||||
slice_loc,
|
||||
slice_len,
|
||||
} => {
|
||||
let s = self.iter.heap.slice_to_str(slice_loc, slice_len);
|
||||
|
||||
match s.chars().next() {
|
||||
@@ -353,7 +364,10 @@ mod test {
|
||||
let mut wam = MockWAM::new();
|
||||
|
||||
let pstr_cell = wam.machine_st.allocate_pstr("abc ").unwrap();
|
||||
wam.machine_st.heap.push_cell(empty_list_as_cell!()).unwrap();
|
||||
wam.machine_st
|
||||
.heap
|
||||
.push_cell(empty_list_as_cell!())
|
||||
.unwrap();
|
||||
|
||||
// not overwriting anything! 0 is an interstitial cell
|
||||
// reserved for use by the runtime
|
||||
@@ -364,7 +378,10 @@ mod test {
|
||||
|
||||
assert_eq!(
|
||||
iter.next(),
|
||||
Some(PStrIteratee::PStrSlice { slice_loc: heap_index!(1), slice_len: "abc ".len() }),
|
||||
Some(PStrIteratee::PStrSlice {
|
||||
slice_loc: heap_index!(1),
|
||||
slice_len: "abc ".len()
|
||||
}),
|
||||
);
|
||||
assert_eq!(iter.next(), None);
|
||||
assert!(!iter.is_cyclic());
|
||||
@@ -384,7 +401,10 @@ mod test {
|
||||
|
||||
assert_eq!(
|
||||
iter.next(),
|
||||
Some(PStrIteratee::PStrSlice { slice_loc: heap_index!(1), slice_len: "abc ".len() })
|
||||
Some(PStrIteratee::PStrSlice {
|
||||
slice_loc: heap_index!(1),
|
||||
slice_len: "abc ".len()
|
||||
})
|
||||
);
|
||||
assert_eq!(
|
||||
iter.next(),
|
||||
@@ -407,7 +427,10 @@ mod test {
|
||||
|
||||
assert_eq!(
|
||||
iter.next(),
|
||||
Some(PStrIteratee::PStrSlice { slice_loc: heap_index!(1), slice_len: "abc ".len() })
|
||||
Some(PStrIteratee::PStrSlice {
|
||||
slice_loc: heap_index!(1),
|
||||
slice_len: "abc ".len()
|
||||
})
|
||||
);
|
||||
assert_eq!(
|
||||
iter.next(),
|
||||
@@ -552,7 +575,11 @@ mod test {
|
||||
section.push_cell(heap_loc_as_cell!(h));
|
||||
});
|
||||
|
||||
unify!(wam.machine_st, pstr_cell, pstr_loc_as_cell!(heap_index!(start)));
|
||||
unify!(
|
||||
wam.machine_st,
|
||||
pstr_cell,
|
||||
pstr_loc_as_cell!(heap_index!(start))
|
||||
);
|
||||
|
||||
assert!(!wam.machine_st.fail);
|
||||
|
||||
@@ -561,7 +588,9 @@ mod test {
|
||||
"abcdef"
|
||||
);
|
||||
assert_eq!(
|
||||
wam.machine_st.heap.slice_to_str(heap_index!(start), "abc".len()),
|
||||
wam.machine_st
|
||||
.heap
|
||||
.slice_to_str(heap_index!(start), "abc".len()),
|
||||
"abc"
|
||||
);
|
||||
assert_eq!(
|
||||
@@ -587,7 +616,10 @@ mod test {
|
||||
|
||||
assert_eq!(
|
||||
iter.next(),
|
||||
Some(PStrIteratee::PStrSlice { slice_loc: 'a'.len_utf8(), slice_len: "bc".len() })
|
||||
Some(PStrIteratee::PStrSlice {
|
||||
slice_loc: 'a'.len_utf8(),
|
||||
slice_len: "bc".len()
|
||||
})
|
||||
);
|
||||
|
||||
for _ in iter {}
|
||||
@@ -609,7 +641,11 @@ mod test {
|
||||
section.push_cell(empty_list_as_cell!());
|
||||
});
|
||||
|
||||
unify!(wam.machine_st, list_loc_as_cell!(start), pstr_loc_as_cell!(0));
|
||||
unify!(
|
||||
wam.machine_st,
|
||||
list_loc_as_cell!(start),
|
||||
pstr_loc_as_cell!(0)
|
||||
);
|
||||
|
||||
assert!(!wam.machine_st.fail);
|
||||
|
||||
@@ -629,7 +665,11 @@ mod test {
|
||||
section.push_cell(empty_list_as_cell!());
|
||||
});
|
||||
|
||||
unify!(wam.machine_st, list_loc_as_cell!(start), pstr_loc_as_cell!(0));
|
||||
unify!(
|
||||
wam.machine_st,
|
||||
list_loc_as_cell!(start),
|
||||
pstr_loc_as_cell!(0)
|
||||
);
|
||||
|
||||
assert_eq!(wam.machine_st.heap[2 + start], char_as_cell!('a'));
|
||||
assert!(!wam.machine_st.fail);
|
||||
@@ -652,7 +692,11 @@ mod test {
|
||||
section.push_cell(empty_list_as_cell!());
|
||||
});
|
||||
|
||||
unify!(wam.machine_st, list_loc_as_cell!(start), pstr_loc_as_cell!(0));
|
||||
unify!(
|
||||
wam.machine_st,
|
||||
list_loc_as_cell!(start),
|
||||
pstr_loc_as_cell!(0)
|
||||
);
|
||||
|
||||
assert_eq!(wam.machine_st.heap[start], char_as_cell!('a'));
|
||||
assert_eq!(wam.machine_st.heap[4 + start], char_as_cell!('b'));
|
||||
@@ -676,7 +720,11 @@ mod test {
|
||||
section.push_cell(empty_list_as_cell!());
|
||||
});
|
||||
|
||||
unify!(wam.machine_st, list_loc_as_cell!(start), pstr_loc_as_cell!(0));
|
||||
unify!(
|
||||
wam.machine_st,
|
||||
list_loc_as_cell!(start),
|
||||
pstr_loc_as_cell!(0)
|
||||
);
|
||||
|
||||
assert_eq!(wam.machine_st.heap[2 + start], char_as_cell!('a'));
|
||||
assert!(!wam.machine_st.fail);
|
||||
@@ -699,10 +747,17 @@ mod test {
|
||||
section.push_cell(heap_loc_as_cell!(5 + start));
|
||||
});
|
||||
|
||||
unify!(wam.machine_st, list_loc_as_cell!(start), pstr_loc_as_cell!(0));
|
||||
unify!(
|
||||
wam.machine_st,
|
||||
list_loc_as_cell!(start),
|
||||
pstr_loc_as_cell!(0)
|
||||
);
|
||||
|
||||
assert_eq!(wam.machine_st.heap[2 + start], char_as_cell!('a'));
|
||||
assert_eq!(wam.machine_st.heap[5 + start], pstr_loc_as_cell!(heap_index!(0) + 3));
|
||||
assert_eq!(
|
||||
wam.machine_st.heap[5 + start],
|
||||
pstr_loc_as_cell!(heap_index!(0) + 3)
|
||||
);
|
||||
assert!(!wam.machine_st.fail);
|
||||
|
||||
// #2293, test6.
|
||||
@@ -723,7 +778,11 @@ mod test {
|
||||
section.push_cell(empty_list_as_cell!());
|
||||
});
|
||||
|
||||
unify!(wam.machine_st, list_loc_as_cell!(start), pstr_loc_as_cell!(0));
|
||||
unify!(
|
||||
wam.machine_st,
|
||||
list_loc_as_cell!(start),
|
||||
pstr_loc_as_cell!(0)
|
||||
);
|
||||
|
||||
assert_eq!(wam.machine_st.heap[start], char_as_cell!('a'));
|
||||
assert_eq!(wam.machine_st.heap[4 + start], char_as_cell!('c'));
|
||||
@@ -750,7 +809,11 @@ mod test {
|
||||
section.push_cell(empty_list_as_cell!());
|
||||
});
|
||||
|
||||
unify!(wam.machine_st, list_loc_as_cell!(start), pstr_loc_as_cell!(0));
|
||||
unify!(
|
||||
wam.machine_st,
|
||||
list_loc_as_cell!(start),
|
||||
pstr_loc_as_cell!(0)
|
||||
);
|
||||
|
||||
assert_eq!(wam.machine_st.heap[2 + start], char_as_cell!('b'));
|
||||
assert_eq!(wam.machine_st.heap[6 + start], char_as_cell!('d'));
|
||||
|
||||
@@ -28,26 +28,26 @@ pub(crate) fn to_op_decl_spec(spec: Atom) -> Result<OpDeclSpec, CompilationError
|
||||
fn setup_op_decl(term: &FocusedHeapRefMut) -> Result<OpDecl, CompilationError> {
|
||||
let (focus, _cell) = subterm_index(term.heap, term.focus);
|
||||
|
||||
let name = match term_predicate_key(term.heap, focus+3) {
|
||||
let name = match term_predicate_key(term.heap, focus + 3) {
|
||||
Some((name, 0)) => name,
|
||||
_ => {
|
||||
return Err(CompilationError::InvalidDirective(
|
||||
DirectiveError::InvalidOpDeclNameType(term.heap[focus+3]),
|
||||
DirectiveError::InvalidOpDeclNameType(term.heap[focus + 3]),
|
||||
));
|
||||
}
|
||||
};
|
||||
|
||||
let spec = match term_predicate_key(term.heap, focus+2) {
|
||||
let spec = match term_predicate_key(term.heap, focus + 2) {
|
||||
Some((name, _)) => name,
|
||||
None => {
|
||||
return Err(CompilationError::InvalidDirective(
|
||||
DirectiveError::InvalidOpDeclSpecDomain(term.heap[focus+2]),
|
||||
DirectiveError::InvalidOpDeclSpecDomain(term.heap[focus + 2]),
|
||||
));
|
||||
}
|
||||
};
|
||||
|
||||
let spec = to_op_decl_spec(spec)?;
|
||||
let prec = term.deref_loc(focus+1);
|
||||
let prec = term.deref_loc(focus + 1);
|
||||
|
||||
let prec = read_heap_cell!(prec,
|
||||
(HeapCellValueTag::Fixnum, n) => {
|
||||
@@ -147,34 +147,34 @@ pub(super) fn setup_module_export_list(
|
||||
let mut focus = term.focus;
|
||||
|
||||
loop {
|
||||
read_heap_cell!(term.heap[focus],
|
||||
(HeapCellValueTag::AttrVar | HeapCellValueTag::Var, h) => {
|
||||
if h == focus {
|
||||
break;
|
||||
} else {
|
||||
focus = h;
|
||||
}
|
||||
}
|
||||
(HeapCellValueTag::Lis, l) => {
|
||||
let term = FocusedHeapRefMut {
|
||||
heap: term.heap,
|
||||
focus: l,
|
||||
};
|
||||
read_heap_cell!(term.heap[focus],
|
||||
(HeapCellValueTag::AttrVar | HeapCellValueTag::Var, h) => {
|
||||
if h == focus {
|
||||
break;
|
||||
} else {
|
||||
focus = h;
|
||||
}
|
||||
}
|
||||
(HeapCellValueTag::Lis, l) => {
|
||||
let term = FocusedHeapRefMut {
|
||||
heap: term.heap,
|
||||
focus: l,
|
||||
};
|
||||
|
||||
exports.push(setup_module_export(&term)?);
|
||||
focus = l + 1;
|
||||
}
|
||||
(HeapCellValueTag::Atom, (name, _arity)) => {
|
||||
if name == atom!("[]") {
|
||||
return Ok(exports);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
break;
|
||||
}
|
||||
);
|
||||
exports.push(setup_module_export(&term)?);
|
||||
focus = l + 1;
|
||||
}
|
||||
(HeapCellValueTag::Atom, (name, _arity)) => {
|
||||
if name == atom!("[]") {
|
||||
return Ok(exports);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
break;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
Err(CompilationError::InvalidModuleDecl)
|
||||
@@ -281,7 +281,7 @@ fn setup_qualified_import(term: FocusedHeapRefMut) -> Result<UseModuleExport, Co
|
||||
* contained in src/lib/ops_and_meta_predicates.pl, which is loaded before
|
||||
* src/lib/builtins.pl.
|
||||
*
|
||||
* Meta-specs have three forms:
|
||||
* Meta-specs have four forms:
|
||||
*
|
||||
* (:) (the argument should be expanded with (:)/2 as described above)
|
||||
* + (mode declarations under the mode syntax, which currently have no effect)
|
||||
@@ -334,7 +334,7 @@ fn setup_meta_predicate<'a, LS: LoadState<'a>>(
|
||||
}
|
||||
|
||||
let heap = loader.machine_heap();
|
||||
let cell = heap_bound_store(heap, heap_bound_deref(heap, heap[term.focus+1]));
|
||||
let cell = heap_bound_store(heap, heap_bound_deref(heap, heap[term.focus + 1]));
|
||||
|
||||
read_heap_cell!(cell,
|
||||
(HeapCellValueTag::Str, s) => {
|
||||
@@ -506,28 +506,27 @@ fn build_meta_predicate_clause<'a, LS: LoadState<'a>>(
|
||||
let (subterm_loc, _) = subterm_index(loader.machine_heap(), subterm_loc);
|
||||
let subterm_key_opt = term_predicate_key(loader.machine_heap(), subterm_loc);
|
||||
|
||||
let (module_name, key, term_loc) =
|
||||
if subterm_key_opt == Some((atom!(":"), 2)) {
|
||||
match get_qualified_name(loader.machine_heap(), subterm_loc + 1, subterm_loc + 2) {
|
||||
Some(QualifiedNameInfo {
|
||||
module_name,
|
||||
name,
|
||||
arity,
|
||||
qualified_term_loc,
|
||||
}) => (
|
||||
module_name,
|
||||
(name, arity + supp_args),
|
||||
qualified_term_loc,
|
||||
),
|
||||
None => {
|
||||
continue;
|
||||
}
|
||||
let (module_name, key, term_loc) = if subterm_key_opt == Some((atom!(":"), 2)) {
|
||||
match get_qualified_name(
|
||||
loader.machine_heap(),
|
||||
subterm_loc + 1,
|
||||
subterm_loc + 2,
|
||||
) {
|
||||
Some(QualifiedNameInfo {
|
||||
module_name,
|
||||
name,
|
||||
arity,
|
||||
qualified_term_loc,
|
||||
}) => (module_name, (name, arity + supp_args), qualified_term_loc),
|
||||
None => {
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
(module_name, (name, arity + supp_args), subterm_loc)
|
||||
};
|
||||
}
|
||||
} else {
|
||||
(module_name, (name, arity + supp_args), subterm_loc)
|
||||
};
|
||||
|
||||
if let Some(index_ptr) = fetch_index_ptr(loader.machine_heap(), key.1, term_loc) {
|
||||
if let Some(index_ptr) = fetch_index_ptr(loader.machine_heap(), term_loc) {
|
||||
index_ptrs.insert(term_loc, index_ptr);
|
||||
continue;
|
||||
}
|
||||
@@ -642,7 +641,12 @@ impl Preprocessor {
|
||||
let classifier = VariableClassifier::new(self.settings.default_call_policy());
|
||||
let var_data = classifier.classify_fact(loader, &term)?;
|
||||
|
||||
Ok((Fact { term_loc: term.focus }, var_data))
|
||||
Ok((
|
||||
Fact {
|
||||
term_loc: term.focus,
|
||||
},
|
||||
var_data,
|
||||
))
|
||||
} else {
|
||||
Err(CompilationError::InadmissibleFact)
|
||||
}
|
||||
@@ -660,7 +664,13 @@ impl Preprocessor {
|
||||
let head_loc = term_nth_arg(heap, term.focus, 1).unwrap();
|
||||
|
||||
if term_predicate_key(heap, head_loc).is_some() {
|
||||
Ok((Rule { term_loc: term.focus, clauses }, var_data))
|
||||
Ok((
|
||||
Rule {
|
||||
term_loc: term.focus,
|
||||
clauses,
|
||||
},
|
||||
var_data,
|
||||
))
|
||||
} else {
|
||||
Err(CompilationError::InvalidRuleHead)
|
||||
}
|
||||
|
||||
@@ -181,10 +181,7 @@ fn pstr_segment_char_count_and_tail(heap: &Heap, pstr_loc: usize) -> (usize, usi
|
||||
byte_offset += c.len_utf8();
|
||||
}
|
||||
|
||||
(
|
||||
char_count,
|
||||
Heap::neighboring_cell_offset(pstr_loc + byte_offset),
|
||||
)
|
||||
(char_count, Heap::pstr_tail_idx(pstr_loc + byte_offset))
|
||||
}
|
||||
|
||||
fn pstr_segment_char_count_up_to(
|
||||
@@ -217,10 +214,9 @@ fn pstr_segment_char_count_up_to(
|
||||
pstr_loc: pstr_loc + byte_offset,
|
||||
}
|
||||
} else {
|
||||
let tail_loc = Heap::neighboring_cell_offset(pstr_loc + byte_offset);
|
||||
PStrSegmentCountResult::End {
|
||||
char_count,
|
||||
tail_loc,
|
||||
tail_loc: Heap::pstr_tail_idx(pstr_loc + byte_offset),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -567,6 +563,12 @@ struct AttrListMatch {
|
||||
prev_tail: Option<usize>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub(crate) struct FindallCopyInfo {
|
||||
offset: usize,
|
||||
pstr_threshold: usize,
|
||||
}
|
||||
|
||||
impl MachineState {
|
||||
#[inline(always)]
|
||||
pub(crate) fn unattributed_var(&mut self) {
|
||||
@@ -648,9 +650,8 @@ impl MachineState {
|
||||
loop {
|
||||
read_heap_cell!(value,
|
||||
(HeapCellValueTag::PStrLoc, h) => {
|
||||
let (_, tail) = heap.scan_slice_to_str(h);
|
||||
// let (h_offset, _) = pstr_loc_and_offset(heap, h);
|
||||
return tail;
|
||||
let HeapStringScan { tail_idx, .. } = heap.scan_slice_to_str(h);
|
||||
return tail_idx;
|
||||
}
|
||||
(HeapCellValueTag::Lis, h) => {
|
||||
return h+1;
|
||||
@@ -855,17 +856,10 @@ impl MachineState {
|
||||
&mut self,
|
||||
lh_offset: usize,
|
||||
copy_target: HeapCellValue,
|
||||
) -> Result<usize, usize> {
|
||||
) -> Result<FindallCopyInfo, usize> {
|
||||
let threshold = self.lifted_heap.cell_len() - lh_offset;
|
||||
|
||||
let mut copy_ball_term = CopyBallTerm::new(
|
||||
&mut self.attr_var_init.attr_var_queue,
|
||||
&mut self.stack,
|
||||
&mut self.heap,
|
||||
&mut self.lifted_heap,
|
||||
);
|
||||
|
||||
let mut writer = copy_ball_term.reserve(3)?;
|
||||
let mut writer = self.lifted_heap.reserve(3)?;
|
||||
|
||||
writer.write_with(|section| {
|
||||
section.push_cell(list_loc_as_cell!(threshold + 1));
|
||||
@@ -873,9 +867,21 @@ impl MachineState {
|
||||
section.push_cell(heap_loc_as_cell!(threshold + 2));
|
||||
});
|
||||
|
||||
copy_term(copy_ball_term, copy_target, AttrVarPolicy::DeepCopy)?;
|
||||
let old_lifted_cell_len = self.lifted_heap.cell_len();
|
||||
|
||||
Ok(threshold + lh_offset + 2)
|
||||
let copy_ball_term = CopyBallTerm::new(
|
||||
&mut self.attr_var_init.attr_var_queue,
|
||||
&mut self.stack,
|
||||
&mut self.heap,
|
||||
&mut self.lifted_heap,
|
||||
);
|
||||
|
||||
let pstr_boundary = copy_term(copy_ball_term, copy_target, AttrVarPolicy::DeepCopy)?;
|
||||
|
||||
Ok(FindallCopyInfo {
|
||||
offset: threshold + lh_offset + 2,
|
||||
pstr_threshold: pstr_boundary + old_lifted_cell_len,
|
||||
})
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
@@ -1045,18 +1051,6 @@ impl MachineState {
|
||||
|
||||
pub fn value_to_str_like(&mut self, value: HeapCellValue) -> Option<AtomOrString> {
|
||||
read_heap_cell!(value,
|
||||
/*
|
||||
(HeapCellValueTag::CStr, cstr_atom) => {
|
||||
// avoid allocating a String if possible:
|
||||
// We must be careful to preserve the string "[]" as is,
|
||||
// instead of turning it into the atom [], i.e., "".
|
||||
if cstr_atom == atom!("[]") {
|
||||
Some(AtomOrString::String("[]".to_string()))
|
||||
} else {
|
||||
Some(AtomOrString::Atom(cstr_atom))
|
||||
}
|
||||
}
|
||||
*/
|
||||
(HeapCellValueTag::Atom, (atom, arity)) => {
|
||||
if arity == 0 {
|
||||
// ... likewise.
|
||||
@@ -1389,15 +1383,7 @@ impl Machine {
|
||||
let (name, arity) = cell_as_atom_cell!(self.machine_st.heap[s])
|
||||
.get_name_and_arity();
|
||||
|
||||
(name, arity, if self.machine_st.heap.cell_len() > s + arity + 1 {
|
||||
if !self.machine_st.heap.pstr_at(s + arity + 1) {
|
||||
get_structure_index(self.machine_st.heap[s + arity + 1])
|
||||
} else {
|
||||
None
|
||||
}
|
||||
} else {
|
||||
None
|
||||
})
|
||||
(name, arity, get_structure_index(self.machine_st.heap[s.saturating_sub(1)]))
|
||||
}
|
||||
(HeapCellValueTag::Atom, (name, arity)) => {
|
||||
debug_assert_eq!(arity, 0);
|
||||
@@ -1457,7 +1443,6 @@ impl Machine {
|
||||
|
||||
if let Some(code_index) = index_cell {
|
||||
if !code_index.is_undefined() {
|
||||
// println!("(fast) calling {}/{}", name.as_str(), arity);
|
||||
load_registers(&mut self.machine_st, goal, goal_arity);
|
||||
self.machine_st.neck_cut();
|
||||
return call_at_index(self, name, arity, code_index.get());
|
||||
@@ -1481,6 +1466,7 @@ impl Machine {
|
||||
.variable_set(&mut supp_vars, self.machine_st.registers[2]);
|
||||
|
||||
struct GoalAnalysisResult {
|
||||
index_ptr_loc: usize,
|
||||
is_simple_goal: bool,
|
||||
goal: HeapCellValue,
|
||||
key: PredicateKey,
|
||||
@@ -1496,7 +1482,7 @@ impl Machine {
|
||||
|
||||
// fill expanded_vars with variables of the partial
|
||||
// goal pre-completion by complete_partial_goal.
|
||||
for idx in s + 1 .. s + arity - supp_vars.len() + 1 {
|
||||
for idx in s + 1 ..= s + arity - supp_vars.len() {
|
||||
self.machine_st.variable_set(&mut expanded_vars, self.machine_st.heap[idx]);
|
||||
}
|
||||
|
||||
@@ -1510,7 +1496,8 @@ impl Machine {
|
||||
// disjoint from them. if they are not, the
|
||||
// expanded goal is not simple.
|
||||
|
||||
let post_supp_args = self.machine_st.heap.splice(s+arity-supp_vars.len()+1 .. s+arity+1);
|
||||
let post_supp_args = (s+arity-supp_vars.len()+1 ..= s+arity)
|
||||
.map(|idx| self.machine_st.heap[idx]);
|
||||
|
||||
post_supp_args
|
||||
.zip(supp_vars.iter())
|
||||
@@ -1535,27 +1522,33 @@ impl Machine {
|
||||
false
|
||||
};
|
||||
|
||||
let goal = if is_simple_goal {
|
||||
let (index_ptr_loc, goal) = if is_simple_goal {
|
||||
let h = self.machine_st.heap.cell_len();
|
||||
let arity = arity - supp_vars.len();
|
||||
|
||||
resource_error_call_result!(
|
||||
self.machine_st,
|
||||
self.machine_st.heap.push_cell(empty_list_as_cell!())
|
||||
);
|
||||
|
||||
resource_error_call_result!(
|
||||
self.machine_st,
|
||||
self.machine_st.heap.copy_slice_to_end(
|
||||
s .. s + arity + 1
|
||||
s ..= s + arity,
|
||||
)
|
||||
);
|
||||
|
||||
self.machine_st.heap[h] = atom_as_cell!(name, arity);
|
||||
self.machine_st.heap[h+1] = atom_as_cell!(name, arity);
|
||||
|
||||
// even if arity == 0, goal must be a Str cell,
|
||||
// since an index is about to appended to it.
|
||||
str_loc_as_cell!(h)
|
||||
(h, str_loc_as_cell!(h+1))
|
||||
} else {
|
||||
goal
|
||||
(0, goal)
|
||||
};
|
||||
|
||||
GoalAnalysisResult {
|
||||
index_ptr_loc,
|
||||
is_simple_goal,
|
||||
goal,
|
||||
key: (name, arity),
|
||||
@@ -1566,36 +1559,25 @@ impl Machine {
|
||||
debug_assert_eq!(arity, 0);
|
||||
|
||||
let h = self.machine_st.heap.cell_len();
|
||||
resource_error_call_result!(
|
||||
|
||||
let mut writer = resource_error_call_result!(
|
||||
self.machine_st,
|
||||
self.machine_st.heap.push_cell(goal)
|
||||
self.machine_st.heap.reserve(2)
|
||||
);
|
||||
|
||||
writer.write_with(|section| {
|
||||
section.push_cell(empty_list_as_cell!());
|
||||
section.push_cell(goal);
|
||||
});
|
||||
|
||||
GoalAnalysisResult {
|
||||
index_ptr_loc: h,
|
||||
is_simple_goal: true,
|
||||
goal: str_loc_as_cell!(h),
|
||||
goal: str_loc_as_cell!(h+1),
|
||||
key: (name, 0),
|
||||
supp_vars,
|
||||
}
|
||||
}
|
||||
/*
|
||||
(HeapCellValueTag::Char, c) => {
|
||||
let name = AtomTable::build_with(&self.machine_st.atom_tbl,&c.to_string());
|
||||
let h = self.machine_st.heap.cell_len();
|
||||
|
||||
resource_error_call_result!(
|
||||
self.machine_st,
|
||||
self.machine_st.heap.push_cell(atom_as_cell!(name))
|
||||
);
|
||||
|
||||
GoalAnalysisResult {
|
||||
is_simple_goal: true,
|
||||
goal: str_loc_as_cell!(h),
|
||||
key: (name, 0),
|
||||
supp_vars,
|
||||
}
|
||||
}
|
||||
*/
|
||||
_ => {
|
||||
self.machine_st.fail = true;
|
||||
return Ok(());
|
||||
@@ -1609,14 +1591,8 @@ impl Machine {
|
||||
|
||||
let expanded_term = if result.is_simple_goal {
|
||||
let idx = self.get_or_insert_qualified_code_index(module_name, result.key);
|
||||
|
||||
resource_error_call_result!(
|
||||
self.machine_st,
|
||||
self.machine_st
|
||||
.heap
|
||||
.push_cell(untyped_arena_ptr_as_cell!(UntypedArenaPtr::from(idx)))
|
||||
);
|
||||
|
||||
self.machine_st.heap[result.index_ptr_loc] =
|
||||
untyped_arena_ptr_as_cell!(UntypedArenaPtr::from(idx));
|
||||
result.goal
|
||||
} else {
|
||||
let mut unexpanded_vars = IndexSet::with_hasher(FxBuildHasher::default());
|
||||
@@ -1648,29 +1624,24 @@ impl Machine {
|
||||
self.machine_st.heap.reserve(unexpanded_vars.len() + 2)
|
||||
);
|
||||
|
||||
writer.write_with(|section| {
|
||||
section.push_cell(atom_as_cell!(atom!("$aux"), 0));
|
||||
|
||||
for value in unexpanded_vars.difference(&result.supp_vars).cloned() {
|
||||
section.push_cell(value);
|
||||
}
|
||||
|
||||
section.push_cell(atom_as_cell!(atom!("[]")));
|
||||
});
|
||||
|
||||
let anon_str_arity = self.machine_st.heap.cell_len() - h - 2;
|
||||
self.machine_st.heap[h] = atom_as_cell!(atom!("$aux"), anon_str_arity);
|
||||
|
||||
let idx = CodeIndex::new(
|
||||
IndexPtr::index(helper_clause_loc),
|
||||
&mut self.machine_st.arena,
|
||||
);
|
||||
|
||||
self.machine_st.heap.last_cell_mut().map(|cell| {
|
||||
*cell = untyped_arena_ptr_as_cell!(UntypedArenaPtr::from(idx));
|
||||
writer.write_with(|section| {
|
||||
section.push_cell(untyped_arena_ptr_as_cell!(UntypedArenaPtr::from(idx)));
|
||||
section.push_cell(atom_as_cell!(atom!("$aux"), 0));
|
||||
|
||||
for value in unexpanded_vars.difference(&result.supp_vars).cloned() {
|
||||
section.push_cell(value);
|
||||
}
|
||||
});
|
||||
|
||||
str_loc_as_cell!(h)
|
||||
let anon_str_arity = self.machine_st.heap.cell_len() - h - 2;
|
||||
self.machine_st.heap[h + 1] = atom_as_cell!(atom!("$aux"), anon_str_arity);
|
||||
|
||||
str_loc_as_cell!(h + 1)
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -1688,28 +1659,22 @@ impl Machine {
|
||||
|
||||
if HeapCellValueTag::Str == qualified_goal.get_tag() {
|
||||
let s = qualified_goal.get_value() as usize;
|
||||
let (name, arity) = cell_as_atom_cell!(self.machine_st.heap[s]).get_name_and_arity();
|
||||
let name = cell_as_atom_cell!(self.machine_st.heap[s]).get_name();
|
||||
|
||||
if name == atom!("$call") {
|
||||
return false;
|
||||
}
|
||||
|
||||
if self.machine_st.heap.cell_len() > s + 1 + arity {
|
||||
if self.machine_st.heap.pstr_at(s + 1 + arity) {
|
||||
return false;
|
||||
}
|
||||
let idx_cell = self.machine_st.heap[s.saturating_sub(1)];
|
||||
|
||||
let idx_cell = self.machine_st.heap[s + 1 + arity];
|
||||
|
||||
if HeapCellValueTag::Cons == idx_cell.get_tag() {
|
||||
match_untyped_arena_ptr!(cell_as_untyped_arena_ptr!(idx_cell),
|
||||
(ArenaHeaderTag::IndexPtr, _ip) => {
|
||||
return true;
|
||||
}
|
||||
_ => {
|
||||
}
|
||||
);
|
||||
}
|
||||
if HeapCellValueTag::Cons == idx_cell.get_tag() {
|
||||
match_untyped_arena_ptr!(cell_as_untyped_arena_ptr!(idx_cell),
|
||||
(ArenaHeaderTag::IndexPtr, _ip) => {
|
||||
return true;
|
||||
}
|
||||
_ => {
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2312,27 +2277,6 @@ impl Machine {
|
||||
let a1 = self.deref_register(1);
|
||||
|
||||
read_heap_cell!(a1,
|
||||
/*
|
||||
(HeapCellValueTag::Char) => {
|
||||
let h = self.machine_st.heap.cell_len();
|
||||
|
||||
let mut writer = resource_error_call_result!(
|
||||
self.machine_st,
|
||||
self.machine_st.heap.reserve(2)
|
||||
);
|
||||
|
||||
step_or_resource_error!(
|
||||
self.machine_st,
|
||||
writer.write_with(|section| {
|
||||
section.push_cell(a1);
|
||||
section.push_cell(empty_list_as_cell!());
|
||||
Ok::<(), usize>(())
|
||||
})
|
||||
);
|
||||
|
||||
unify!(self.machine_st, self.machine_st.registers[2], list_loc_as_cell!(h));
|
||||
}
|
||||
*/
|
||||
(HeapCellValueTag::Atom, (name, arity)) => {
|
||||
debug_assert_eq!(arity, 0);
|
||||
|
||||
@@ -2542,7 +2486,7 @@ impl Machine {
|
||||
self.machine_st.allocate_pstr(&*atom.as_str())
|
||||
);
|
||||
|
||||
let tail_loc = Heap::neighboring_cell_offset(atom.as_str().len() + heap_index!(pstr_h));
|
||||
let tail_loc = Heap::pstr_tail_idx(atom.as_str().len() + heap_index!(pstr_h));
|
||||
|
||||
step_or_resource_error!(
|
||||
self.machine_st,
|
||||
@@ -2585,8 +2529,8 @@ impl Machine {
|
||||
|
||||
read_heap_cell!(pstr,
|
||||
(HeapCellValueTag::PStrLoc, h) => {
|
||||
let (_, tail_loc) = self.machine_st.heap.scan_slice_to_str(h);
|
||||
unify_fn!(self.machine_st, heap_loc_as_cell!(tail_loc), a2);
|
||||
let HeapStringScan { tail_idx, .. } = self.machine_st.heap.scan_slice_to_str(h);
|
||||
unify_fn!(self.machine_st, heap_loc_as_cell!(tail_idx), a2);
|
||||
}
|
||||
(HeapCellValueTag::Lis, h) => {
|
||||
unify_fn!(
|
||||
@@ -3970,7 +3914,10 @@ impl Machine {
|
||||
pub(crate) fn copy_to_lifted_heap(&mut self) {
|
||||
let lh_offset = cell_as_fixnum!(self.deref_register(1)).get_num() as usize;
|
||||
let copy_target = self.machine_st.registers[2];
|
||||
let old_threshold = step_or_resource_error!(
|
||||
let FindallCopyInfo {
|
||||
offset: old_threshold,
|
||||
pstr_threshold,
|
||||
} = step_or_resource_error!(
|
||||
self.machine_st,
|
||||
self.machine_st
|
||||
.copy_findall_solution(lh_offset, copy_target)
|
||||
@@ -3980,8 +3927,20 @@ impl Machine {
|
||||
|
||||
self.machine_st.lifted_heap[old_threshold] = heap_loc_as_cell!(new_threshold);
|
||||
|
||||
for addr in &mut self.machine_st.lifted_heap.splice_mut(old_threshold + 1..) {
|
||||
*addr -= self.machine_st.heap.cell_len() + lh_offset;
|
||||
for idx in old_threshold + 1..pstr_threshold {
|
||||
self.machine_st.lifted_heap[idx] -= self.machine_st.heap.cell_len() + lh_offset;
|
||||
}
|
||||
|
||||
let mut pstr_threshold = heap_index!(pstr_threshold);
|
||||
|
||||
while pstr_threshold < heap_index!(self.machine_st.lifted_heap.cell_len()) {
|
||||
let HeapStringScan { tail_idx, .. } = self
|
||||
.machine_st
|
||||
.lifted_heap
|
||||
.scan_slice_to_str(pstr_threshold);
|
||||
|
||||
self.machine_st.lifted_heap[tail_idx] -= self.machine_st.heap.cell_len() + lh_offset;
|
||||
pstr_threshold = heap_index!(tail_idx + 1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5797,17 +5756,18 @@ impl Machine {
|
||||
unify_fn!(self.machine_st, solutions, diff);
|
||||
} else {
|
||||
let h = self.machine_st.heap.cell_len();
|
||||
let reserve_size = self.machine_st.lifted_heap.cell_len() - lh_offset;
|
||||
|
||||
step_or_resource_error!(
|
||||
let mut writer = step_or_resource_error!(
|
||||
self.machine_st,
|
||||
self.machine_st
|
||||
.heap
|
||||
.append(self.machine_st.lifted_heap.splice(lh_offset..),)
|
||||
self.machine_st.heap.reserve(reserve_size)
|
||||
);
|
||||
|
||||
for cell in &mut self.machine_st.heap.splice_mut(h..) {
|
||||
*cell = *cell + h;
|
||||
}
|
||||
writer.write_with(|section| {
|
||||
for idx in lh_offset..self.machine_st.lifted_heap.cell_len() {
|
||||
section.push_cell(self.machine_st.lifted_heap[idx] + h);
|
||||
}
|
||||
});
|
||||
|
||||
let diff = self.machine_st.registers[3];
|
||||
unify_fn!(
|
||||
@@ -5834,17 +5794,18 @@ impl Machine {
|
||||
unify_fn!(self.machine_st, solutions, empty_list_as_cell!());
|
||||
} else {
|
||||
let h = self.machine_st.heap.cell_len();
|
||||
let reserve_size = self.machine_st.lifted_heap.cell_len() - lh_offset;
|
||||
|
||||
step_or_resource_error!(
|
||||
let mut writer = step_or_resource_error!(
|
||||
self.machine_st,
|
||||
self.machine_st
|
||||
.heap
|
||||
.append(self.machine_st.lifted_heap.splice(lh_offset..),)
|
||||
self.machine_st.heap.reserve(reserve_size)
|
||||
);
|
||||
|
||||
for cell in &mut self.machine_st.heap.splice_mut(h..) {
|
||||
*cell = *cell + h;
|
||||
}
|
||||
writer.write_with(|section| {
|
||||
for idx in lh_offset..self.machine_st.lifted_heap.cell_len() {
|
||||
section.push_cell(self.machine_st.lifted_heap[idx] + h);
|
||||
}
|
||||
});
|
||||
|
||||
self.machine_st.lifted_heap.truncate(lh_offset);
|
||||
|
||||
@@ -7223,8 +7184,7 @@ impl Machine {
|
||||
let mut ball = Ball::new();
|
||||
|
||||
ball.boundary = self.machine_st.heap.cell_len();
|
||||
|
||||
step_or_resource_error!(
|
||||
ball.pstr_boundary = step_or_resource_error!(
|
||||
self.machine_st,
|
||||
copy_term(
|
||||
CopyBallTerm::new(
|
||||
|
||||
@@ -44,14 +44,19 @@ impl<'a> BootstrappingTermStream<'a> {
|
||||
listing_src: ListingSource,
|
||||
) -> Self {
|
||||
let lexer_parser = LexerParser::new(stream, machine_st);
|
||||
Self { lexer_parser, listing_src }
|
||||
Self {
|
||||
lexer_parser,
|
||||
listing_src,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> TermStream for BootstrappingTermStream<'a> {
|
||||
#[inline]
|
||||
fn next(&mut self, op_dir: &CompositeOpDir) -> Result<TermWriteResult, CompilationError> {
|
||||
let result = self.lexer_parser.read_term(op_dir, Tokens::Default)
|
||||
let result = self
|
||||
.lexer_parser
|
||||
.read_term(op_dir, Tokens::Default)
|
||||
.map_err(CompilationError::from);
|
||||
|
||||
result
|
||||
@@ -125,7 +130,9 @@ pub struct InlineTermStream {}
|
||||
|
||||
impl TermStream for InlineTermStream {
|
||||
fn next(&mut self, _: &CompositeOpDir) -> Result<TermWriteResult, CompilationError> {
|
||||
Err(CompilationError::from(ParserError::unexpected_eof(ParserErrorSrc::default())))
|
||||
Err(CompilationError::from(ParserError::unexpected_eof(
|
||||
ParserErrorSrc::default(),
|
||||
)))
|
||||
}
|
||||
|
||||
fn eof(&mut self) -> Result<bool, CompilationError> {
|
||||
|
||||
@@ -507,11 +507,9 @@ fn bind_with_occurs_check<U: Unifier>(unifier: &mut U, r: Ref, value: HeapCellVa
|
||||
if value.is_ref() && !value.is_stack_var() {
|
||||
machine_st.heap[0] = value;
|
||||
|
||||
for cell in stackful_preorder_iter::<NonListElider>(
|
||||
&mut machine_st.heap,
|
||||
&mut machine_st.stack,
|
||||
0,
|
||||
) {
|
||||
for cell in
|
||||
stackful_preorder_iter::<NonListElider>(&mut machine_st.heap, &mut machine_st.stack, 0)
|
||||
{
|
||||
let cell = unmark_cell_bits!(cell);
|
||||
|
||||
if let Some(inner_r) = cell.as_var() {
|
||||
|
||||
@@ -141,7 +141,11 @@ macro_rules! fixnum {
|
||||
($n:expr, $arena:expr) => {
|
||||
Fixnum::build_with_checked($n)
|
||||
.map(|n| fixnum_as_cell!(n))
|
||||
.unwrap_or_else(|_| typed_arena_ptr_as_cell!(arena_alloc!(Integer::from($n), $arena) as TypedArenaPtr<Integer>))
|
||||
.unwrap_or_else(|_| {
|
||||
typed_arena_ptr_as_cell!(
|
||||
arena_alloc!(Integer::from($n), $arena) as TypedArenaPtr<Integer>
|
||||
)
|
||||
})
|
||||
};
|
||||
($wrapper:ty, $n:expr, $arena:expr) => {
|
||||
Fixnum::build_with_checked($n)
|
||||
@@ -619,10 +623,7 @@ impl Literal {
|
||||
|
||||
pub type Var = Rc<String>;
|
||||
|
||||
pub(crate) fn subterm_index(
|
||||
heap: &impl SizedHeap,
|
||||
subterm_loc: usize,
|
||||
) -> (usize, HeapCellValue) {
|
||||
pub(crate) fn subterm_index(heap: &impl SizedHeap, subterm_loc: usize) -> (usize, HeapCellValue) {
|
||||
let subterm = heap[subterm_loc];
|
||||
|
||||
if subterm.is_ref() {
|
||||
@@ -715,16 +716,10 @@ pub fn unfold_by_str(mut term: Term, s: Atom) -> Vec<Term> {
|
||||
}
|
||||
*/
|
||||
|
||||
pub(crate) fn fetch_index_ptr(
|
||||
heap: &impl SizedHeap,
|
||||
arity: usize,
|
||||
term_loc: usize,
|
||||
) -> Option<CodeIndex> {
|
||||
if term_loc + arity + 1 >= heap.cell_len() || heap.pstr_at(term_loc + arity + 1) {
|
||||
return None;
|
||||
}
|
||||
pub(crate) fn fetch_index_ptr(heap: &impl SizedHeap, term_loc: usize) -> Option<CodeIndex> {
|
||||
let index_cell_loc = term_loc.saturating_sub(1);
|
||||
|
||||
read_heap_cell!(heap[term_loc + arity + 1],
|
||||
read_heap_cell!(heap[index_cell_loc],
|
||||
(HeapCellValueTag::Cons, c) => {
|
||||
match_untyped_arena_ptr!(c,
|
||||
(ArenaHeaderTag::IndexPtr, ptr) => {
|
||||
@@ -744,7 +739,7 @@ pub(crate) fn blunt_index_ptr(
|
||||
key: PredicateKey,
|
||||
term_loc: usize,
|
||||
) -> bool {
|
||||
if fetch_index_ptr(heap, key.1, term_loc).is_some() {
|
||||
if fetch_index_ptr(heap, term_loc).is_some() {
|
||||
heap[term_loc] = atom_as_cell!(key.0, key.1);
|
||||
true
|
||||
} else {
|
||||
@@ -757,10 +752,7 @@ pub(crate) fn unfold_by_str_once(
|
||||
start_term: HeapCellValue,
|
||||
atom: Atom,
|
||||
) -> Option<usize> {
|
||||
let start_term = heap_bound_store(
|
||||
heap,
|
||||
heap_bound_deref(heap, start_term),
|
||||
);
|
||||
let start_term = heap_bound_store(heap, heap_bound_deref(heap, start_term));
|
||||
|
||||
if let HeapCellValueTag::Str = start_term.get_tag() {
|
||||
let s = start_term.get_value() as usize;
|
||||
@@ -769,7 +761,7 @@ pub(crate) fn unfold_by_str_once(
|
||||
blunt_index_ptr(heap, (s_atom, s_arity), s);
|
||||
|
||||
if (s_atom, s_arity) == (atom, 2) {
|
||||
return Some(s+1);
|
||||
return Some(s + 1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -826,7 +818,7 @@ pub fn unfold_by_str_locs(
|
||||
let mut current_term = heap[term_loc];
|
||||
|
||||
while let Some(fst_loc) = unfold_by_str_once(heap, current_term, atom) {
|
||||
term_loc = fst_loc+1;
|
||||
term_loc = fst_loc + 1;
|
||||
current_term = heap[term_loc];
|
||||
let fst = heap[fst_loc];
|
||||
terms.push((fst, fst_loc));
|
||||
@@ -836,10 +828,7 @@ pub fn unfold_by_str_locs(
|
||||
terms
|
||||
}
|
||||
|
||||
pub fn term_predicate_key(
|
||||
heap: &impl SizedHeap,
|
||||
mut term_loc: usize,
|
||||
) -> Option<PredicateKey> {
|
||||
pub fn term_predicate_key(heap: &impl SizedHeap, mut term_loc: usize) -> Option<PredicateKey> {
|
||||
loop {
|
||||
read_heap_cell!(heap[term_loc],
|
||||
(HeapCellValueTag::Atom, (name, arity)) => {
|
||||
@@ -879,10 +868,7 @@ pub fn inverse_var_locs_from_iter<I: Iterator<Item = HeapCellValue>>(iter: I) ->
|
||||
let var_loc = var.get_value() as usize;
|
||||
|
||||
if count > 1 {
|
||||
inverse_var_locs.insert(
|
||||
var_loc,
|
||||
Rc::new(format!("_{}", var_loc)),
|
||||
);
|
||||
inverse_var_locs.insert(var_loc, Rc::new(format!("_{}", var_loc)));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -56,22 +56,18 @@ impl Token {
|
||||
Token::String(string) if flags.double_quotes.is_codes() => {
|
||||
2 * string.chars().count() + 1
|
||||
}
|
||||
Token::String(string) => {
|
||||
Heap::compute_pstr_size(&string)
|
||||
}
|
||||
Token::Literal(_) |
|
||||
Token::Comma |
|
||||
Token::HeadTailSeparator |
|
||||
Token::Open |
|
||||
Token::OpenCT |
|
||||
Token::OpenCurly |
|
||||
Token::OpenList |
|
||||
Token::Var(_) => {
|
||||
Token::String(string) => Heap::compute_pstr_size(&string),
|
||||
Token::Literal(_)
|
||||
| Token::Comma
|
||||
| Token::HeadTailSeparator
|
||||
| Token::Open
|
||||
| Token::OpenCT
|
||||
| Token::OpenCurly
|
||||
| Token::OpenList
|
||||
| Token::Var(_) => {
|
||||
heap_index!(1)
|
||||
}
|
||||
_ => {
|
||||
0
|
||||
}
|
||||
_ => 0,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -462,10 +458,7 @@ impl<'a, R: CharRead> LexerParser<'a, R> {
|
||||
self.skip_char(c);
|
||||
u32::from_str_radix(&token, radix).map_or_else(
|
||||
|_| Err(ParserError::ParseBigInt(self.loc_to_err_src())),
|
||||
|n| {
|
||||
char::try_from(n)
|
||||
.map_err(|_| ParserError::Utf8Error(self.loc_to_err_src()))
|
||||
},
|
||||
|n| char::try_from(n).map_err(|_| ParserError::Utf8Error(self.loc_to_err_src())),
|
||||
)
|
||||
} else {
|
||||
Err(ParserError::IncompleteReduction(self.loc_to_err_src()))
|
||||
@@ -657,7 +650,9 @@ impl<'a, R: CharRead> LexerParser<'a, R> {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return Err(ParserError::InvalidSingleQuotedCharacter(self.loc_to_err_src()));
|
||||
return Err(ParserError::InvalidSingleQuotedCharacter(
|
||||
self.loc_to_err_src(),
|
||||
));
|
||||
}
|
||||
} else {
|
||||
match self.get_back_quoted_string() {
|
||||
|
||||
@@ -187,7 +187,9 @@ struct Parser<'a> {
|
||||
inverse_var_locs: InverseVarLocs,
|
||||
}
|
||||
|
||||
pub fn read_tokens<R: CharRead>(lexer: &mut LexerParser<R>) -> Result<(Vec<Token>, usize), ParserError> {
|
||||
pub fn read_tokens<R: CharRead>(
|
||||
lexer: &mut LexerParser<R>,
|
||||
) -> Result<(Vec<Token>, usize), ParserError> {
|
||||
let mut tokens = vec![];
|
||||
let mut term_size = 0;
|
||||
|
||||
@@ -264,9 +266,9 @@ pub(crate) fn as_partial_string(
|
||||
tail = heap[l+1];
|
||||
}
|
||||
(HeapCellValueTag::PStrLoc, l) => {
|
||||
let (pstr, tail_loc) = heap.scan_slice_to_str(l);
|
||||
let HeapStringScan { string: pstr, tail_idx } = heap.scan_slice_to_str(l);
|
||||
string += pstr;
|
||||
tail = heap[tail_loc];
|
||||
tail = heap[tail_idx];
|
||||
}
|
||||
(HeapCellValueTag::AttrVar | HeapCellValueTag::Var, h) => {
|
||||
if heap[h] != tail {
|
||||
@@ -306,8 +308,7 @@ impl<'a> Parser<'a> {
|
||||
TokenType::Comma => Some(atom!(",")),
|
||||
TokenType::Term { heap_loc } => {
|
||||
if heap_loc.is_ref() {
|
||||
term_predicate_key(&self.terms, heap_loc.get_value() as usize)
|
||||
.map(|key| key.0)
|
||||
term_predicate_key(&self.terms, heap_loc.get_value() as usize).map(|key| key.0)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
@@ -392,7 +393,8 @@ impl<'a> Parser<'a> {
|
||||
|
||||
fn promote_atom_op(&mut self, atom: Atom, priority: usize, assoc: u32) {
|
||||
let h = self.terms.cell_len();
|
||||
self.terms.write_with(|section| section.push_cell(atom_as_cell!(atom)));
|
||||
self.terms
|
||||
.write_with(|section| section.push_cell(atom_as_cell!(atom)));
|
||||
self.stack.push(TokenDesc {
|
||||
tt: TokenType::Term {
|
||||
heap_loc: heap_loc_as_cell!(h),
|
||||
@@ -438,10 +440,12 @@ impl<'a> Parser<'a> {
|
||||
section.push_cell(list_loc_as_cell!(h));
|
||||
});
|
||||
|
||||
TokenType::Term { heap_loc: heap_loc_as_cell!(h + 2) }
|
||||
TokenType::Term {
|
||||
heap_loc: heap_loc_as_cell!(h + 2),
|
||||
}
|
||||
} else {
|
||||
self.terms.write_with(|section| {
|
||||
match section.push_pstr(&s) {
|
||||
self.terms
|
||||
.write_with(|section| match section.push_pstr(&s) {
|
||||
Some(pstr_loc_cell) => {
|
||||
section.push_cell(empty_list_as_cell!());
|
||||
let h = section.cell_len();
|
||||
@@ -451,10 +455,11 @@ impl<'a> Parser<'a> {
|
||||
None => {
|
||||
section.push_cell(empty_list_as_cell!());
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
TokenType::Term { heap_loc: pstr_cell }
|
||||
TokenType::Term {
|
||||
heap_loc: pstr_cell,
|
||||
}
|
||||
}
|
||||
}
|
||||
Token::Literal(c) => {
|
||||
@@ -478,13 +483,14 @@ impl<'a> Parser<'a> {
|
||||
|
||||
if var.trim() != "_" {
|
||||
self.var_locs.insert(var.clone(), heap_loc);
|
||||
self.inverse_var_locs.insert(heap_loc.get_value() as usize, var);
|
||||
self.inverse_var_locs
|
||||
.insert(heap_loc.get_value() as usize, var);
|
||||
}
|
||||
|
||||
TokenType::Term { heap_loc }
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
Token::Comma => TokenType::Comma,
|
||||
Token::Open => TokenType::Open,
|
||||
Token::Close => TokenType::Close,
|
||||
@@ -619,15 +625,21 @@ impl<'a> Parser<'a> {
|
||||
let term_idx = self.terms.cell_len();
|
||||
|
||||
let push_structure = |parser: &mut Self, name: Atom| -> TokenType {
|
||||
parser.terms.write_with(|section| section.push_cell(atom_as_cell!(name, arity)));
|
||||
parser
|
||||
.terms
|
||||
.write_with(|section| section.push_cell(atom_as_cell!(name, arity)));
|
||||
|
||||
for idx in (stack_len + 2..parser.stack.len()).step_by(2) {
|
||||
let subterm = parser.term_from_stack(idx).unwrap();
|
||||
parser.terms.write_with(|section| section.push_cell(subterm));
|
||||
parser
|
||||
.terms
|
||||
.write_with(|section| section.push_cell(subterm));
|
||||
}
|
||||
|
||||
let str_loc_idx = parser.terms.cell_len();
|
||||
parser.terms.write_with(|section| section.push_cell(str_loc_as_cell!(term_idx)));
|
||||
parser
|
||||
.terms
|
||||
.write_with(|section| section.push_cell(str_loc_as_cell!(term_idx)));
|
||||
|
||||
TokenType::Term {
|
||||
heap_loc: heap_loc_as_cell!(str_loc_idx),
|
||||
@@ -709,23 +721,20 @@ impl<'a> Parser<'a> {
|
||||
}
|
||||
|
||||
fn loc_to_err_src(&self) -> ParserErrorSrc {
|
||||
ParserErrorSrc { line_num: *self.line_num, col_num: *self.col_num }
|
||||
ParserErrorSrc {
|
||||
line_num: *self.line_num,
|
||||
col_num: *self.col_num,
|
||||
}
|
||||
}
|
||||
|
||||
fn expand_comma_compacted_terms(&mut self, index: usize) -> usize {
|
||||
if let Some(term) = self.term_from_stack(index - 1) {
|
||||
let mut op_desc = self.stack[index - 1];
|
||||
let mut term = heap_bound_store(
|
||||
&self.terms,
|
||||
heap_bound_deref(
|
||||
&self.terms,
|
||||
term,
|
||||
),
|
||||
);
|
||||
let mut term = heap_bound_store(&self.terms, heap_bound_deref(&self.terms, term));
|
||||
|
||||
if term.is_ref() &&
|
||||
0 < op_desc.priority &&
|
||||
op_desc.priority < self.stack[index].priority
|
||||
if term.is_ref()
|
||||
&& 0 < op_desc.priority
|
||||
&& op_desc.priority < self.stack[index].priority
|
||||
{
|
||||
/* '|' is a head-tail separator here, not
|
||||
* an operator, so expand the
|
||||
@@ -740,11 +749,9 @@ impl<'a> Parser<'a> {
|
||||
} else {
|
||||
let mut terms = vec![];
|
||||
|
||||
while let Some(fst_loc) = unfold_by_str_once(
|
||||
&mut self.terms,
|
||||
term,
|
||||
atom!(","),
|
||||
) {
|
||||
while let Some(fst_loc) =
|
||||
unfold_by_str_once(&mut self.terms, term, atom!(","))
|
||||
{
|
||||
let (_, snd) = subterm_index(&self.terms, fst_loc + 1);
|
||||
let (_, fst) = subterm_index(&self.terms, fst_loc);
|
||||
|
||||
@@ -763,14 +770,13 @@ impl<'a> Parser<'a> {
|
||||
};
|
||||
|
||||
let arity = terms.len() - 1;
|
||||
self.stack.extend(terms.into_iter().map(|heap_loc| {
|
||||
TokenDesc {
|
||||
self.stack
|
||||
.extend(terms.into_iter().map(|heap_loc| TokenDesc {
|
||||
tt: TokenType::Term { heap_loc },
|
||||
priority: 0,
|
||||
spec: 0,
|
||||
unfold_bounds: 0,
|
||||
}
|
||||
}));
|
||||
}));
|
||||
return arity;
|
||||
}
|
||||
}
|
||||
@@ -816,7 +822,8 @@ impl<'a> Parser<'a> {
|
||||
// parsed an empty list token
|
||||
if td.tt == TokenType::OpenList {
|
||||
let h = self.terms.cell_len();
|
||||
self.terms.write_with(|section| section.push_cell(empty_list_as_cell!()));
|
||||
self.terms
|
||||
.write_with(|section| section.push_cell(empty_list_as_cell!()));
|
||||
|
||||
td.spec = TERM;
|
||||
td.tt = TokenType::Term {
|
||||
@@ -845,9 +852,7 @@ impl<'a> Parser<'a> {
|
||||
let tail_term = match self.term_from_stack(idx + 1) {
|
||||
Some(term) => term,
|
||||
None => {
|
||||
return Err(ParserError::IncompleteReduction(
|
||||
self.loc_to_err_src(),
|
||||
));
|
||||
return Err(ParserError::IncompleteReduction(self.loc_to_err_src()));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -863,18 +868,14 @@ impl<'a> Parser<'a> {
|
||||
};
|
||||
|
||||
if arity > self.terms.cell_len() {
|
||||
return Err(ParserError::IncompleteReduction(
|
||||
self.loc_to_err_src(),
|
||||
));
|
||||
return Err(ParserError::IncompleteReduction(self.loc_to_err_src()));
|
||||
}
|
||||
|
||||
let pre_terms_len = self.terms.cell_len();
|
||||
|
||||
while let Some(token_desc) = self.stack.pop() {
|
||||
let subterm = match token_desc.tt {
|
||||
TokenType::Term { heap_loc } => {
|
||||
heap_loc
|
||||
}
|
||||
TokenType::Term { heap_loc } => heap_loc,
|
||||
_ => {
|
||||
continue;
|
||||
}
|
||||
@@ -942,7 +943,8 @@ impl<'a> Parser<'a> {
|
||||
if td.tt == TokenType::OpenCurly {
|
||||
let h = self.terms.cell_len();
|
||||
|
||||
self.terms.write_with(|section| section.push_cell(atom_as_cell!(atom!("{}"))));
|
||||
self.terms
|
||||
.write_with(|section| section.push_cell(atom_as_cell!(atom!("{}"))));
|
||||
|
||||
td.tt = TokenType::Term {
|
||||
heap_loc: heap_loc_as_cell!(h),
|
||||
@@ -1160,66 +1162,58 @@ impl<'a> Parser<'a> {
|
||||
Token::String(string) => {
|
||||
self.shift(Token::String(string), 0, TERM);
|
||||
}
|
||||
Token::Literal(c) => {
|
||||
match Number::try_from(c) {
|
||||
Ok(Number::Integer(n)) => {
|
||||
self.negate_number(n, negate_int_rc, |n, _| typed_arena_ptr_as_cell!(n))
|
||||
}
|
||||
Ok(Number::Rational(n)) => {
|
||||
self.negate_number(n, negate_rat_rc, |r, _| typed_arena_ptr_as_cell!(r))
|
||||
}
|
||||
Ok(Number::Float(n)) if n.is_infinite() => {
|
||||
return Err(ParserError::InfiniteFloat(
|
||||
self.lexer.loc_to_err_src(),
|
||||
));
|
||||
}
|
||||
Ok(Number::Float(n)) => {
|
||||
use ordered_float::OrderedFloat;
|
||||
Token::Literal(c) => match Number::try_from(c) {
|
||||
Ok(Number::Integer(n)) => {
|
||||
self.negate_number(n, negate_int_rc, |n, _| typed_arena_ptr_as_cell!(n))
|
||||
}
|
||||
Ok(Number::Rational(n)) => {
|
||||
self.negate_number(n, negate_rat_rc, |r, _| typed_arena_ptr_as_cell!(r))
|
||||
}
|
||||
Ok(Number::Float(n)) if n.is_infinite() => {
|
||||
return Err(ParserError::InfiniteFloat(
|
||||
self.loc_to_err_src(),
|
||||
));
|
||||
}
|
||||
Ok(Number::Float(n)) => {
|
||||
use ordered_float::OrderedFloat;
|
||||
|
||||
self.negate_number(
|
||||
n,
|
||||
|n, _| -n,
|
||||
|OrderedFloat(n), arena| HeapCellValue::from(float_alloc!(n, arena)),
|
||||
)
|
||||
}
|
||||
Ok(Number::Fixnum(n)) => {
|
||||
self.negate_number(n, |n, _| -n, |n, _| fixnum_as_cell!(n))
|
||||
}
|
||||
Err(_) => {
|
||||
if let Some(name) = c.to_atom() {
|
||||
if !self.shift_op(name, op_dir)? {
|
||||
self.shift(Token::Literal(c), 0, TERM);
|
||||
}
|
||||
} else {
|
||||
self.negate_number(
|
||||
n,
|
||||
|n, _| -n,
|
||||
|OrderedFloat(n), arena| HeapCellValue::from(float_alloc!(n, arena)),
|
||||
)
|
||||
}
|
||||
Ok(Number::Fixnum(n)) => {
|
||||
self.negate_number(n, |n, _| -n, |n, _| fixnum_as_cell!(n))
|
||||
}
|
||||
Err(_) => {
|
||||
if let Some(name) = c.to_atom() {
|
||||
if !self.shift_op(name, op_dir)? {
|
||||
self.shift(Token::Literal(c), 0, TERM);
|
||||
}
|
||||
} else {
|
||||
self.shift(Token::Literal(c), 0, TERM);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
Token::Var(v) => self.shift(Token::Var(v), 0, TERM),
|
||||
Token::Open => self.shift(Token::Open, 1300, DELIMITER),
|
||||
Token::OpenCT => self.shift(Token::OpenCT, 1300, DELIMITER),
|
||||
Token::Close => {
|
||||
if !self.reduce_term() && !self.reduce_brackets() {
|
||||
return Err(ParserError::IncompleteReduction(
|
||||
self.loc_to_err_src(),
|
||||
));
|
||||
return Err(ParserError::IncompleteReduction(self.loc_to_err_src()));
|
||||
}
|
||||
}
|
||||
Token::OpenList => self.shift(Token::OpenList, 1300, DELIMITER),
|
||||
Token::CloseList => {
|
||||
if !self.reduce_list()? {
|
||||
return Err(ParserError::IncompleteReduction(
|
||||
self.loc_to_err_src(),
|
||||
));
|
||||
return Err(ParserError::IncompleteReduction(self.loc_to_err_src()));
|
||||
}
|
||||
}
|
||||
Token::OpenCurly => self.shift(Token::OpenCurly, 1300, DELIMITER),
|
||||
Token::CloseCurly => {
|
||||
if !self.reduce_curly()? {
|
||||
return Err(ParserError::IncompleteReduction(
|
||||
self.loc_to_err_src(),
|
||||
));
|
||||
return Err(ParserError::IncompleteReduction(self.loc_to_err_src()));
|
||||
}
|
||||
}
|
||||
Token::HeadTailSeparator => {
|
||||
@@ -1253,9 +1247,7 @@ impl<'a> Parser<'a> {
|
||||
| Some(TokenType::OpenCurly)
|
||||
| Some(TokenType::HeadTailSeparator)
|
||||
| Some(TokenType::Comma) => {
|
||||
return Err(ParserError::IncompleteReduction(
|
||||
self.loc_to_err_src(),
|
||||
))
|
||||
return Err(ParserError::IncompleteReduction(self.loc_to_err_src()))
|
||||
}
|
||||
_ => {}
|
||||
},
|
||||
@@ -1272,7 +1264,10 @@ impl<'a, R: CharRead> LexerParser<'a, R> {
|
||||
}
|
||||
|
||||
pub fn loc_to_err_src(&self) -> ParserErrorSrc {
|
||||
ParserErrorSrc { line_num: self.line_num, col_num: self.col_num }
|
||||
ParserErrorSrc {
|
||||
line_num: self.line_num,
|
||||
col_num: self.col_num,
|
||||
}
|
||||
}
|
||||
|
||||
// on success, returns the parsed term and the number of lines read.
|
||||
@@ -1289,7 +1284,11 @@ impl<'a, R: CharRead> LexerParser<'a, R> {
|
||||
// the parser uses conditional indirection in many places so
|
||||
// the reserved size should be at least 4 * term_byte_size
|
||||
// so all cells are accounted for.
|
||||
let writer = match self.machine_st.heap.reserve(cell_index!(4 * term_byte_size)) {
|
||||
let writer = match self
|
||||
.machine_st
|
||||
.heap
|
||||
.reserve(cell_index!(4 * term_byte_size))
|
||||
{
|
||||
Ok(term) => term,
|
||||
Err(_err_loc) => {
|
||||
return Err(ParserError::ResourceError(self.loc_to_err_src()));
|
||||
|
||||
@@ -58,7 +58,7 @@ impl MachineState {
|
||||
let op_dir = CompositeOpDir::new(op_dir, None);
|
||||
|
||||
let term_result = lexer_parser.read_term(&op_dir, Tokens::Default);
|
||||
let lines_read = lexer_parser.line_num();
|
||||
let lines_read = lexer_parser.line_num();
|
||||
|
||||
term_result.map(|term| (term, lines_read))
|
||||
}
|
||||
|
||||
14
src/types.rs
14
src/types.rs
@@ -369,8 +369,8 @@ impl HeapCellValue {
|
||||
name == atom!("[]") && arity == 0
|
||||
}
|
||||
(HeapCellValueTag::PStrLoc, h) => {
|
||||
let (_s, tail_loc) = heap.scan_slice_to_str(h);
|
||||
self = heap[tail_loc];
|
||||
let HeapStringScan { tail_idx, .. } = heap.scan_slice_to_str(h);
|
||||
self = heap[tail_idx];
|
||||
continue;
|
||||
}
|
||||
(HeapCellValueTag::AttrVar | HeapCellValueTag::Var, h) => {
|
||||
@@ -399,8 +399,7 @@ impl HeapCellValue {
|
||||
| HeapCellValueTag::Var
|
||||
| HeapCellValueTag::StackVar
|
||||
| HeapCellValueTag::AttrVar
|
||||
| HeapCellValueTag::PStrLoc
|
||||
// | HeapCellValueTag::PStrOffset
|
||||
| HeapCellValueTag::PStrLoc // | HeapCellValueTag::PStrOffset
|
||||
)
|
||||
}
|
||||
|
||||
@@ -503,9 +502,7 @@ impl HeapCellValue {
|
||||
#[inline]
|
||||
pub fn to_atom(self) -> Option<Atom> {
|
||||
match self.get_tag() {
|
||||
HeapCellValueTag::Atom => {
|
||||
Some(AtomCell::from_bytes(self.into_bytes()).get_name())
|
||||
}
|
||||
HeapCellValueTag::Atom => Some(AtomCell::from_bytes(self.into_bytes()).get_name()),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
@@ -775,7 +772,8 @@ impl Sub<i64> for HeapCellValue {
|
||||
HeapCellValue::build_with(tag, self.get_value() + rhs.unsigned_abs())
|
||||
}
|
||||
tag @ HeapCellValueTag::PStrLoc => {
|
||||
let value = self.get_value() as usize + heap_index!(rhs.unsigned_abs() as usize);
|
||||
let value =
|
||||
self.get_value() as usize + heap_index!(rhs.unsigned_abs() as usize);
|
||||
HeapCellValue::build_with(tag, value as u64)
|
||||
}
|
||||
_ => self,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use crate::parser::ast::*;
|
||||
use crate::forms::GenContext;
|
||||
use crate::parser::ast::*;
|
||||
|
||||
use bit_set::*;
|
||||
use fxhash::FxBuildHasher;
|
||||
@@ -88,7 +88,10 @@ pub enum VarAlloc {
|
||||
safety: VarSafetyStatus,
|
||||
to_perm_var_num: Option<usize>,
|
||||
},
|
||||
Perm { reg: usize, allocation: PermVarAllocation }, // stack offset, allocation info
|
||||
Perm {
|
||||
reg: usize,
|
||||
allocation: PermVarAllocation,
|
||||
}, // stack offset, allocation info
|
||||
}
|
||||
|
||||
impl VarAlloc {
|
||||
@@ -152,7 +155,10 @@ pub struct VariableRecord {
|
||||
impl Default for VariableRecord {
|
||||
fn default() -> Self {
|
||||
VariableRecord {
|
||||
allocation: VarAlloc::Perm { reg: 0, allocation: PermVarAllocation::Pending },
|
||||
allocation: VarAlloc::Perm {
|
||||
reg: 0,
|
||||
allocation: PermVarAllocation::Pending,
|
||||
},
|
||||
num_occurrences: 0,
|
||||
running_count: 0,
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user