Revert "remove Term"

This reverts commit 3b5879841aedecba5057c70c71da0ba23e5cd84a.
This commit is contained in:
Mark Thom
2025-03-15 13:19:26 -07:00
committed by Mark Thom
parent eef7b06919
commit 9e1e99f961
53 changed files with 3726 additions and 4517 deletions

View File

@@ -1126,7 +1126,10 @@ impl MachineState {
match Number::try_from(value) {
Ok(n) => Ok(n),
Err(_) => self.arith_eval_by_metacall(value),
Err(_) => {
self.heap[0] = value;
self.arith_eval_by_metacall(0)
}
}
}
&ArithmeticTerm::Interm(i) => Ok(mem::replace(
@@ -1152,21 +1155,11 @@ impl MachineState {
pub(crate) fn arith_eval_by_metacall(
&mut self,
value: HeapCellValue,
term_loc: usize,
) -> Result<Number, MachineStub> {
debug_assert!(value.is_ref());
let stub_gen = || functor_stub(atom!("is"), 2);
let root_loc = if value.is_ref() && !value.is_stack_var() {
value.get_value() as usize
} else {
let type_error = self.type_error(ValidType::Evaluable, value);
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);
stackful_post_order_iter::<NonListElider>(&mut self.heap, &mut self.stack, term_loc);
while let Some(value) = iter.next() {
if value.get_forwarding_bit() {
@@ -1459,7 +1452,7 @@ mod tests {
parse_and_write_parsed_term_to_heap(&mut wam, "3 + 4 - 1 + 2.", &op_dir).unwrap();
assert_eq!(
wam.arith_eval_by_metacall(heap_loc_as_cell!(term_write_result.focus)),
wam.arith_eval_by_metacall(term_write_result.heap_loc),
Ok(Number::Fixnum(Fixnum::build_with(8))),
);
@@ -1469,7 +1462,7 @@ mod tests {
parse_and_write_parsed_term_to_heap(&mut wam, "5 * 4 - 1.", &op_dir).unwrap();
assert_eq!(
wam.arith_eval_by_metacall(heap_loc_as_cell!(term_write_result.focus)),
wam.arith_eval_by_metacall(term_write_result.heap_loc),
Ok(Number::Fixnum(Fixnum::build_with(19))),
);
@@ -1479,7 +1472,7 @@ mod tests {
parse_and_write_parsed_term_to_heap(&mut wam, "sign(-1).", &op_dir).unwrap();
assert_eq!(
wam.arith_eval_by_metacall(heap_loc_as_cell!(term_write_result.focus)),
wam.arith_eval_by_metacall(term_write_result.heap_loc),
Ok(Number::Fixnum(Fixnum::build_with(-1)))
);
}

View File

@@ -10,8 +10,8 @@ use std::cmp::Ordering;
pub(super) type Bindings = Vec<(usize, HeapCellValue)>;
#[derive(Debug)]
pub(crate) struct AttrVarInitializer {
pub(crate) attr_var_queue: Vec<usize>,
pub(super) struct AttrVarInitializer {
pub(super) attr_var_queue: Vec<usize>,
pub(super) bindings: Bindings,
pub(super) p: usize,
pub(super) cp: usize,
@@ -138,17 +138,10 @@ impl MachineState {
let mut seen_set = IndexSet::new();
let mut seen_vars = vec![];
let root_loc = if cell.is_ref() {
cell.get_value() as usize
} else {
return vec![];
};
let mut iter = stackful_preorder_iter::<NonListElider>(
&mut self.heap,
&mut self.stack,
root_loc, // cell,
);
self.heap[0] = cell;
let mut iter = stackful_preorder_iter::<NonListElider>(&mut self.heap, &mut self.stack, 0);
while let Some(value) = iter.next() {
read_heap_cell!(value,

View File

@@ -11,6 +11,7 @@ use crate::machine::term_stream::*;
use crate::machine::*;
use crate::parser::ast::*;
use std::cell::Cell;
use std::collections::VecDeque;
use std::mem;
use std::ops::Range;
@@ -1232,16 +1233,14 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
fn compile_standalone_clause(
&mut self,
term: TermWriteResult,
term: Term,
settings: CodeGenSettings,
) -> Result<StandaloneCompileResult, SessionError> {
let mut preprocessor = Preprocessor::new(settings);
let clause = preprocessor.try_term_to_tl(self, term)?;
let machine_st = LS::machine_st(&mut self.payload);
let mut cg = CodeGenerator::new(settings);
let clause_code = cg.compile_predicate(&mut machine_st.heap, vec![clause])?;
let mut cg = CodeGenerator::new(settings);
let clause_code = cg.compile_predicate(vec![clause])?;
Ok(StandaloneCompileResult {
clause_code,
@@ -1262,6 +1261,10 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
let code_len = self.wam_prelude.code.len();
let mut code_ptr = code_len;
if key == (atom!("..."), 2) {
print!("");
}
let mut clauses = vec![];
let mut preprocessor = Preprocessor::new(settings);
@@ -1269,10 +1272,8 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
clauses.push(preprocessor.try_term_to_tl(self, term)?);
}
let machine_st = LS::machine_st(&mut self.payload);
let mut cg = CodeGenerator::new(settings);
let mut code = cg.compile_predicate(&mut machine_st.heap, clauses)?;
let mut code = cg.compile_predicate(clauses)?;
if settings.is_extensible {
let mut clause_clause_locs = VecDeque::new();
@@ -1469,7 +1470,7 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
pub(super) fn incremental_compile_clause(
&mut self,
key: PredicateKey,
clause: TermWriteResult,
clause: Term,
compilation_target: CompilationTarget,
non_counted_bt: bool,
append_or_prepend: AppendOrPrepend,
@@ -2004,13 +2005,16 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
}
impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
pub(super) fn compile_clause_clauses(
pub(super) fn compile_clause_clauses<ClauseIter: Iterator<Item = (Term, Term)>>(
&mut self,
key: PredicateKey,
compilation_target: CompilationTarget,
clause_clauses: Vec<TermWriteResult>,
clause_clauses: ClauseIter,
append_or_prepend: AppendOrPrepend,
) -> Result<(), SessionError> {
let clause_predicates = clause_clauses
.map(|(head, body)| Term::Clause(Cell::default(), atom!("$clause"), vec![head, body]));
let clause_clause_compilation_target = match compilation_target {
CompilationTarget::User => CompilationTarget::Module(atom!("builtins")),
_ => compilation_target,
@@ -2018,7 +2022,7 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
let mut num_clause_predicates = 0;
for clause_term in clause_clauses {
for clause_term in clause_predicates {
self.incremental_compile_clause(
(atom!("$clause"), 2),
clause_term,
@@ -2102,13 +2106,15 @@ 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 = self
.payload
.predicates
.first()
.and_then(|cl| {
let arity = ClauseInfo::arity(cl);
ClauseInfo::name(cl).map(|name| (name, arity))
})
.ok_or(SessionError::NamelessEntry)?;
let listing_src_file_name = self.listing_src_file_name();
@@ -2247,12 +2253,13 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
.clause_clauses
.drain(0..std::cmp::min(predicates_len, clause_clauses_len))
.collect();
let compilation_target = self.payload.predicates.compilation_target;
self.compile_clause_clauses(
key,
compilation_target,
clauses_vec,
clauses_vec.into_iter(),
AppendOrPrepend::Append,
)?;
}
@@ -2281,50 +2288,15 @@ impl Machine {
pub(crate) fn compile_standalone_clause(
&mut self,
term_reg: RegType,
vars: Vec<HeapCellValue>,
term_loc: RegType,
vars: &[Term],
) -> Result<(), SessionError> {
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)
.map_err(|_err_loc| ParserError::ResourceError(ParserErrorSrc::default()))?;
writer.write_with(move |section| {
section.push_cell(atom_as_cell!(atom!(""), arity));
for var in vars {
section.push_cell(var);
}
let head_loc = if arity > 0 {
str_loc_as_cell!(new_header_loc)
} else {
heap_loc_as_cell!(new_header_loc)
};
section.push_cell(atom_as_cell!(atom!(":-"), 2));
section.push_cell(head_loc);
section.push_cell(body_cell);
});
let mut compile = || {
let mut loader: Loader<'_, InlineLoadState<'_>> =
Loader::new(self, InlineTermStream {});
let machine_st = InlineLoadState::machine_st(&mut loader.payload);
let term_loc = str_loc_as_cell!(term_loc);
let term = TermWriteResult::from(&mut machine_st.heap, term_loc)
.map_err(|_err_loc| ParserError::ResourceError(ParserErrorSrc::default()))?;
let term = loader.read_term_from_heap(term_loc);
let clause = build_rule_body(vars, term);
let settings = CodeGenSettings {
global_clock_tick: None,
@@ -2332,7 +2304,7 @@ impl Machine {
non_counted_bt: true,
};
loader.compile_standalone_clause(term, settings)
loader.compile_standalone_clause(clause, settings)
};
let StandaloneCompileResult { clause_code, .. } = compile()?;

File diff suppressed because it is too large Load Diff

View File

@@ -2829,7 +2829,7 @@ impl Machine {
Some(PStrCmpResult::PartialPStrMatch { string, var_loc }) => {
let cell = backtrack_on_resource_error!(
self.machine_st,
self.machine_st.allocate_pstr(string)
self.machine_st.heap.allocate_pstr(string)
);
self.machine_st.mode = MachineMode::Write;
@@ -2851,7 +2851,7 @@ impl Machine {
HeapCellValueTag::Var) => {
let target_cell = backtrack_on_resource_error!(
self.machine_st,
self.machine_st.allocate_pstr(string)
self.machine_st.heap.allocate_pstr(string)
);
self.machine_st.bind(
@@ -3196,7 +3196,7 @@ impl Machine {
&Instruction::PutPartialString(_, ref string, reg) => {
self.machine_st[reg] = backtrack_on_resource_error!(
self.machine_st,
self.machine_st.allocate_pstr(&string)
self.machine_st.heap.allocate_pstr(&string)
);
self.machine_st.p += 1;

View File

@@ -1,3 +1,10 @@
#[cfg(test)]
use fxhash::FxBuildHasher;
#[cfg(test)]
use indexmap::IndexMap;
#[cfg(test)]
use std::collections::BTreeMap;
#[cfg(test)]
use crate::atom_table::*;
#[cfg(test)]
@@ -8,17 +15,6 @@ use crate::types::*;
#[cfg(test)]
use crate::heap_iter::{FocusedHeapIter, HeapOrStackTag, IterStackLoc};
#[cfg(test)]
use std::collections::BTreeMap;
#[cfg(test)]
use std::ops::Deref;
#[cfg(test)]
use fxhash::FxBuildHasher;
#[cfg(test)]
use indexmap::IndexMap;
#[cfg(test)]
pub(crate) trait UnmarkPolicy {
fn forward_attr_var(iter: &mut StacklessPreOrderHeapIter<Self>) -> Option<HeapCellValue>
@@ -185,15 +181,6 @@ pub(crate) struct StacklessPreOrderHeapIter<'a, UMP: UnmarkPolicy> {
pstr_loc_values: PStrLocValuesMap,
}
#[cfg(test)]
impl<'a> Deref for StacklessPreOrderHeapIter<'a, IteratorUMP> {
type Target = Heap;
fn deref(&self) -> &Self::Target {
self.heap
}
}
#[cfg(test)]
impl<'a> FocusedHeapIter for StacklessPreOrderHeapIter<'a, IteratorUMP> {
#[inline]
@@ -778,7 +765,7 @@ mod tests {
// two-part complete string, then a three-part cyclic string
// involving an uncompacted list of chars.
let pstr_cell = wam.machine_st.allocate_pstr("abc ").unwrap();
let pstr_cell = wam.machine_st.heap.allocate_pstr("abc ").unwrap();
wam.machine_st.heap.push_cell(heap_loc_as_cell!(1)).unwrap();
@@ -812,7 +799,7 @@ mod tests {
wam.machine_st.heap[1] = pstr_loc_as_cell!(heap_index!(3));
wam.machine_st.allocate_pstr("abcdef ").unwrap();
wam.machine_st.heap.allocate_pstr("abcdef ").unwrap();
wam.machine_st.heap.push_cell(heap_loc_as_cell!(5)).unwrap();
mark_cells(&mut wam.machine_st.heap, 2);

View File

@@ -4,13 +4,12 @@ use crate::functor_macro::*;
use crate::types::*;
use std::alloc;
use std::cmp::Ordering;
use std::convert::TryFrom;
use std::ops::{Bound, Index, IndexMut, Range, RangeBounds};
use std::ptr;
use std::sync::Once;
use super::MachineState;
const ALIGN: usize = Heap::heap_cell_alignment();
#[derive(Debug)]
@@ -92,9 +91,10 @@ pub struct HeapStringScan<'a> {
}
// return the string at ptr and the tail location relative to ptr.
unsafe fn scan_slice_to_str<'a>(heap_slice: &'a [u8]) -> HeapStringScan<'a> {
unsafe fn scan_slice_to_str(heap_slice: &[u8]) -> HeapStringScan {
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)
@@ -111,79 +111,9 @@ unsafe fn scan_slice_to_str<'a>(heap_slice: &'a [u8]) -> HeapStringScan<'a> {
#[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,
},
}
impl PStrSegmentCmpResult {
pub(crate) fn continue_pstr_compare(
self,
pdl: &mut Vec<HeapCellValue>,
) -> Option<std::cmp::Ordering> {
match self {
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::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,
} => {
// exhaustive match
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));
}
PStrSegmentCmpResult::Mismatch { c1, c2 } => {
return Some(c1.cmp(&c2));
}
}
None
}
}
#[derive(Debug)]
pub struct PStrWriteInfo {
cell: HeapCellValue,
Less,
Greater,
Continue(HeapCellValue, HeapCellValue),
}
#[derive(Debug)]
@@ -269,7 +199,6 @@ impl ReservedHeapSection {
}
self.push_cell(char_as_cell!('\u{0}'));
src = &src[1..];
}
@@ -277,8 +206,6 @@ impl ReservedHeapSection {
return ret;
}
debug_assert!(!src.is_empty());
if let Some(null_char_idx) = src.find('\u{0}') {
debug_assert_ne!(null_char_idx, 0);
@@ -300,6 +227,7 @@ impl ReservedHeapSection {
self.push_cell(char_as_cell!('\u{0}'));
src = &src[null_char_idx + 1..];
if src.is_empty() {
return ret;
}
@@ -316,7 +244,6 @@ impl ReservedHeapSection {
}
self.push_pstr_segment(&src);
return ret;
}
}
@@ -449,23 +376,6 @@ impl<'a> HeapWriter<'a> {
result,
}
}
#[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.heap_byte_len = heap_index!(cell_offset);
}
#[inline]
pub(crate) fn is_empty(&self) -> bool {
self.section.heap_cell_len == 0
}
#[inline]
pub(crate) fn cell_len(&self) -> usize {
self.section.heap_cell_len
}
}
impl<'a> Index<usize> for HeapWriter<'a> {
@@ -517,8 +427,6 @@ impl<'a> SizedHeap for HeapWriter<'a> {
}
}
impl<'a> SizedHeapMut for HeapWriter<'a> {}
impl Heap {
pub(crate) fn new() -> Self {
Self {
@@ -638,16 +546,6 @@ impl Heap {
self.inner.byte_len == 0
}
pub(crate) fn index_of(&mut self, cell: HeapCellValue) -> Result<usize, usize> {
Ok(if cell.is_var() {
cell.get_value() as usize
} else {
let focus = self.cell_len();
self.push_cell(cell)?;
focus
})
}
pub(crate) fn clear(&mut self) {
unsafe {
let layout = alloc::Layout::array::<u8>(self.inner.byte_cap).unwrap();
@@ -699,48 +597,69 @@ impl Heap {
pstr_loc1: usize,
pstr_loc2: usize,
) -> PStrSegmentCmpResult {
unsafe {
let slice1 = std::slice::from_raw_parts(
self.inner.ptr.add(pstr_loc1),
self.inner.byte_len - pstr_loc1,
);
let slice1 = &self.as_slice()[pstr_loc1..];
let slice2 = &self.as_slice()[pstr_loc2..];
let slice2 = std::slice::from_raw_parts(
self.inner.ptr.add(pstr_loc2),
self.inner.byte_len - pstr_loc2,
);
let find_tail = |null_idx: usize| -> usize { self.scan_slice_to_str(null_idx).tail_idx };
let str1 = std::str::from_utf8_unchecked(&slice1);
let str2 = std::str::from_utf8_unchecked(&slice2);
match slice1
.iter()
.zip(slice2.iter())
.position(|(b1, b2)| b1 != b2 || *b1 == 0 || *b2 == 0)
{
Some(pos) => {
if slice1[pos] == 0 {
// subtract 1 from pos to offset the increment of scan_slice_to_str if the
// string is "\0\".
let tail1_idx = find_tail(pstr_loc1 + pos);
debug_assert!(!str1.is_empty());
debug_assert!(!str2.is_empty());
if slice2[pos] == 0 {
let tail2_idx = find_tail(pstr_loc2 + pos);
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,
};
} else if c1 == '\u{0}' {
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,
};
} else if c1 != c2 {
return PStrSegmentCmpResult::Mismatch { c1, c2 };
PStrSegmentCmpResult::Continue(
heap_loc_as_cell!(tail1_idx),
heap_loc_as_cell!(tail2_idx),
)
} else {
PStrSegmentCmpResult::Continue(
heap_loc_as_cell!(tail1_idx),
pstr_loc_as_cell!(pstr_loc2 + pos),
)
}
} else if slice2[pos] == 0 {
let tail2_idx = find_tail(pstr_loc2 + pos);
PStrSegmentCmpResult::Continue(
pstr_loc_as_cell!(pstr_loc1 + pos),
heap_loc_as_cell!(tail2_idx),
)
} else {
// Compute 7-byte chunks with the mismatching character at pos in the middle of
// each. This way, the character of which the byte at pos is a part will be
// validated and reached eventually by the utf8_chunks() iterator.
let slice1_range = pos.saturating_sub(3)..(pos + 4).min(slice1.len());
let slice2_range = pos.saturating_sub(3)..(pos + 4).min(slice2.len());
let chars1_iter = slice1[slice1_range].utf8_chunks();
let chars2_iter = slice2[slice2_range].utf8_chunks();
for (chunk1, chunk2) in chars1_iter.zip(chars2_iter) {
let result = chunk1.valid().cmp(chunk2.valid());
if result == Ordering::Greater {
return PStrSegmentCmpResult::Greater;
} else if result == Ordering::Less {
return PStrSegmentCmpResult::Less;
}
}
unreachable!()
}
}
unreachable!() // PStrSegmentCmpResult::Match(std::cmp::min(str1.len(), str2.len()))
None => {
unreachable!()
}
}
}
@@ -833,43 +752,34 @@ impl Heap {
Range { start, end }
}
/*
pub(crate) fn splice<R: RangeBounds<usize>>(
&self,
range: R,
) -> HeapView {
let range = self.slice_range(range);
HeapView {
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],
}
}
pub(crate) fn splice_mut<R: RangeBounds<usize>>(
&self,
range: R,
) -> HeapViewMut {
let range = self.slice_range(range);
HeapViewMut {
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],
}
}
*/
pub fn allocate_pstr(&mut self, src: &str) -> Result<Option<PStrWriteInfo>, usize> {
pub fn allocate_pstr(&mut self, src: &str) -> Result<HeapCellValue, usize> {
let size_in_heap = Self::compute_pstr_size(src);
let mut writer = self.reserve(size_in_heap)?;
let HeapSectionWriteResult { result, .. } =
writer.write_with(|section| section.push_pstr(src));
writer.write_with(|section| match section.push_pstr(src) {
None => empty_list_as_cell!(),
Some(cell) => cell,
});
Ok(result.map(|cell| PStrWriteInfo { cell }))
Ok(result)
}
// note that allocate_cstr emits a tail cell to the string (completing it with the empty list)
// unlike any version of allocate_pstr.
pub fn allocate_cstr(&mut self, src: &str) -> Result<HeapCellValue, usize> {
let size_in_heap = Self::compute_pstr_size(src);
let mut writer = self.reserve(size_in_heap + 1)?;
let HeapSectionWriteResult { result, .. } =
writer.write_with(|section| match section.push_pstr(src) {
None => empty_list_as_cell!(),
Some(cell) => {
section.push_cell(empty_list_as_cell!());
cell
}
});
Ok(result)
}
pub const fn heap_cell_alignment() -> usize {
@@ -1007,7 +917,7 @@ impl Heap {
// 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 {
if (null_idx + 1).next_multiple_of(ALIGN) == null_idx + 1 {
byte_size += 2 * size_of::<HeapCellValue>();
} else {
byte_size += size_of::<HeapCellValue>();
@@ -1107,27 +1017,6 @@ impl<'a> Iterator for PStrSegmentIter<'a> {
}
}
impl MachineState {
pub(crate) fn allocate_pstr(&mut self, src: &str) -> Result<HeapCellValue, usize> {
match self.heap.allocate_pstr(src)? {
None => Ok(empty_list_as_cell!()),
Some(PStrWriteInfo { cell }) => Ok(cell),
}
}
// note that allocate_cstr emits a tail cell to the string (completing it with the empty list)
// unlike any version of allocate_pstr.
pub(crate) fn allocate_cstr(&mut self, src: &str) -> Result<HeapCellValue, usize> {
match self.heap.allocate_pstr(src)? {
None => Ok(empty_list_as_cell!()),
Some(PStrWriteInfo { cell }) => {
self.heap.push_cell(empty_list_as_cell!())?;
Ok(cell)
}
}
}
}
pub trait SizedHeap: Index<usize, Output = HeapCellValue> {
// return the size of the instance in cells
fn cell_len(&self) -> usize;
@@ -1141,8 +1030,6 @@ pub trait SizedHeap: Index<usize, Output = HeapCellValue> {
// fn pstr_at(&self, cell_offset: usize) -> bool;
}
pub trait SizedHeapMut: IndexMut<usize, Output = HeapCellValue> + SizedHeap {}
impl Index<usize> for Heap {
type Output = HeapCellValue;
@@ -1183,8 +1070,6 @@ impl SizedHeap for Heap {
}
}
impl SizedHeapMut for Heap {}
// 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

View File

@@ -1,15 +1,18 @@
use std::cmp::Ordering;
use std::collections::BTreeMap;
use std::rc::Rc;
use crate::atom_table;
use crate::heap_iter::{stackful_post_order_iter, NonListElider};
use crate::machine::machine_indices::VarKey;
use crate::machine::mock_wam::CompositeOpDir;
use crate::machine::{
ArenaHeaderTag, F64Offset, F64Ptr, Fixnum, Number, BREAK_FROM_DISPATCH_LOOP_LOC,
LIB_QUERY_SUCCESS,
};
use crate::parser::ast::{TermWriteResult, Var};
use crate::parser::lexer::LexerParser;
use crate::parser::parser::Tokens;
use crate::parser::ast::{Var, VarPtr};
use crate::parser::parser::{Parser, Tokens};
use crate::read::{write_term_to_heap, TermWriteResult};
use crate::types::UntypedArenaPtr;
use dashu::{Integer, Rational};
@@ -169,7 +172,7 @@ impl Term {
pub(crate) fn from_heapcell(
machine: &mut Machine,
heap_cell: HeapCellValue,
var_names: &mut IndexMap<HeapCellValue, Var>,
var_names: &mut IndexMap<HeapCellValue, VarPtr>,
) -> Self {
// Adapted from MachineState::read_term_from_heap
let mut term_stack = vec![];
@@ -183,6 +186,16 @@ impl Term {
);
let mut anon_count: usize = 0;
let var_ptr_cmp = |a, b| match a {
Var::Named(name_a) => match b {
Var::Named(name_b) => name_a.cmp(&name_b),
_ => Ordering::Less,
},
_ => match b {
Var::Named(_) => Ordering::Greater,
_ => Ordering::Equal,
},
};
while let Some(addr) = iter.next() {
let addr = unmark_cell_bits!(addr);
@@ -233,33 +246,34 @@ impl Term {
term_stack.push(list);
}
(HeapCellValueTag::Var | HeapCellValueTag::AttrVar | HeapCellValueTag::StackVar) => {
let var = var_names.get(&addr).cloned();
let var = var_names.get(&addr).map(|x| x.borrow().clone());
match var {
Some(name) => term_stack.push(Term::Var(name.to_string())),
Some(Var::Named(name)) => term_stack.push(Term::Var(name.as_ref().to_owned())),
_ => {
let anon_name = loop {
// Generate a name for the anonymous variable
let anon_name = count_to_letter_code(anon_count);
let anon_name = Rc::new(count_to_letter_code(anon_count));
// Find if this name is already being used
var_names.sort_by(|_, a, _, b| a.cmp(b));
var_names.sort_by(|_, a, _, b| {
var_ptr_cmp(a.borrow().clone(), b.borrow().clone())
});
let binary_result = var_names.binary_search_by(|_,a| {
let a: &String = a.as_ref();
a.cmp(&anon_name)
let var_ptr = Var::Named(anon_name.clone());
var_ptr_cmp(a.borrow().clone(), var_ptr.clone())
});
match binary_result {
Ok(_) => anon_count += 1, // Name already used
Err(_) => {
// Name not used, assign it to this variable
let var = anon_name.clone();
var_names.insert(addr, Var::from(var));
let var_ptr = VarPtr::from(Var::Named(anon_name.clone()));
var_names.insert(addr, var_ptr);
break anon_name;
},
}
};
term_stack.push(Term::Var(anon_name));
term_stack.push(Term::Var(anon_name.as_ref().to_owned()));
},
}
}
@@ -401,7 +415,7 @@ pub struct QueryState<'a> {
machine: &'a mut Machine,
term: TermWriteResult,
stub_b: usize,
var_names: IndexMap<HeapCellValue, Var>,
var_names: IndexMap<HeapCellValue, VarPtr>,
called: bool,
}
@@ -465,7 +479,7 @@ impl Iterator for QueryState<'_> {
}
if machine.machine_st.p == LIB_QUERY_SUCCESS {
if term_write_result.inverse_var_locs.is_empty() {
if term_write_result.var_dict.is_empty() {
self.machine.machine_st.backtrack();
return Some(Ok(LeafAnswer::True));
}
@@ -474,39 +488,47 @@ impl Iterator for QueryState<'_> {
}
let mut bindings: BTreeMap<String, Term> = BTreeMap::new();
let inverse_var_locs = &term_write_result.inverse_var_locs;
for (var_loc, var_name) in inverse_var_locs.iter() {
let var_dict = &term_write_result.var_dict;
for (var_key, term_to_be_printed) in var_dict.iter() {
let mut var_name = var_key.to_string();
if var_name.starts_with('_') {
let should_print = var_names.values().any(|v| v == var_name);
let should_print = var_names.values().any(|x| match x.borrow().clone() {
Var::Named(v) => *v == *var_name,
_ => false,
});
if !should_print {
continue;
}
}
let var_loc = *var_loc;
let term =
Term::from_heapcell(machine, heap_loc_as_cell!(var_loc), &mut var_names.clone());
let mut term =
Term::from_heapcell(machine, *term_to_be_printed, &mut var_names.clone());
if let Term::Var(ref term_str) = term {
if *term_str == **var_name {
if *term_str == var_name {
continue;
}
// inverse_var_locs is in the order things appear in
// the query. If var_name appears after term in the
// query, switch their places.
let var_cell = machine
.machine_st
.store(machine.machine_st.deref(machine.machine_st.heap[var_loc]));
if (var_cell.get_value() as usize) < var_loc {
bindings.insert(term_str.clone(), Term::Var(var_name.to_string()));
continue;
// Var dict is in the order things appear in the query. If var_name appears
// after term in the query, switch their places.
let var_name_idx = var_dict
.get_index_of(&VarKey::VarPtr(Var::from(var_name.clone()).into()))
.unwrap();
let term_idx =
var_dict.get_index_of(&VarKey::VarPtr(Var::from(term_str.clone()).into()));
if let Some(idx) = term_idx {
if idx < var_name_idx {
let new_term = Term::Var(var_name);
let new_var_name = term_str.into();
term = new_term;
var_name = new_var_name;
}
}
}
bindings.insert(var_name.to_string(), term);
bindings.insert(var_name, term);
}
// NOTE: there are outstanding choicepoints, backtrack
@@ -530,9 +552,9 @@ impl Machine {
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_as_cell!(stream);
self.machine_st.registers[2] = atom_as_cell!(atom_table::AtomTable::build_with(
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));
@@ -564,7 +586,7 @@ impl Machine {
/// Runs a query.
pub fn run_query(&mut self, query: impl Into<String>) -> QueryState {
let mut parser = LexerParser::new(
let mut parser = Parser::new(
Stream::from_owned_string(query.into(), &mut self.machine_st.arena),
&mut self.machine_st,
);
@@ -575,10 +597,26 @@ impl Machine {
self.allocate_stub_choice_point();
// Write term to heap
self.machine_st.registers[1] = self.machine_st.heap[term.focus];
self.machine_st.cp = LIB_QUERY_SUCCESS; // BREAK_FROM_DISPATCH_LOOP_LOC;
// Write parsed term to heap
let term_write_result = write_term_to_heap(&term, &mut self.machine_st.heap)
.expect("couldn't write term to heap");
let var_names: IndexMap<_, _> = term_write_result
.var_dict
.iter()
.map(|(var_key, cell)| match var_key {
// NOTE: not the intention behind Var::InSitu here but
// we can hijack it to store anonymous variables
// without creating problems.
VarKey::AnonVar(h) => (*cell, VarPtr::from(Var::InSitu(*h))),
VarKey::VarPtr(var_ptr) => (*cell, var_ptr.clone()),
})
.collect();
// Write term to heap
self.machine_st.registers[1] = self.machine_st.heap[term_write_result.heap_loc];
self.machine_st.cp = LIB_QUERY_SUCCESS; // BREAK_FROM_DISPATCH_LOOP_LOC;
let call_index_p = self
.indices
.code_dir
@@ -587,22 +625,12 @@ impl Machine {
.local()
.unwrap();
let var_names: IndexMap<_, _> = term
.inverse_var_locs
.iter()
.map(|(var_loc, var)| {
let cell = self.machine_st.heap[*var_loc];
(cell, var.clone())
})
.collect();
self.machine_st.execute_at_index(1, call_index_p);
let stub_b = self.machine_st.b;
QueryState {
machine: self,
term,
term: term_write_result,
stub_b,
var_names,
called: false,

View File

@@ -1150,8 +1150,7 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
let mut path_buf = PathBuf::from(&*filename.as_str());
path_buf.set_extension("pl");
let file = File::open(&path_buf)
.map_err(|err| ParserError::IO(err, ParserErrorSrc::default()))?;
let file = File::open(&path_buf)?;
(
Stream::from_file_as_input(
@@ -1232,8 +1231,7 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
ModuleSource::File(filename) => {
let mut path_buf = PathBuf::from(&*filename.as_str());
path_buf.set_extension("pl");
let file = File::open(&path_buf)
.map_err(|err| ParserError::IO(err, ParserErrorSrc::default()))?;
let file = File::open(&path_buf)?;
(
Stream::from_file_as_input(

View File

@@ -15,28 +15,12 @@ use crate::types::*;
use indexmap::IndexSet;
use std::cell::Cell;
use std::collections::VecDeque;
use std::convert::TryFrom;
use std::fmt;
use std::ops::{Deref, DerefMut};
impl TermWriteResult {
pub(super) fn from(heap: &mut Heap, value: HeapCellValue) -> Result<Self, usize> {
let focus = heap.index_of(value)?;
let mut stack = Stack::uninitialized();
heap[0] = value;
let inverse_var_locs = inverse_var_locs_from_iter(stackful_preorder_iter::<NonListElider>(
heap, &mut stack, 0,
));
Ok(Self {
focus,
inverse_var_locs,
})
}
}
use std::rc::Rc;
/*
* The loader compiles Prolog terms read from a TermStream instance,
@@ -194,18 +178,18 @@ impl CompilationTarget {
}
pub struct PredicateQueue {
pub predicates: Vec<TermWriteResult>,
pub compilation_target: CompilationTarget,
pub(super) predicates: Vec<Term>,
pub(super) compilation_target: CompilationTarget,
}
impl PredicateQueue {
#[inline]
pub(super) fn push(&mut self, term_write_result: TermWriteResult) {
self.predicates.push(term_write_result);
pub(super) fn push(&mut self, clause: Term) {
self.predicates.push(clause);
}
#[inline]
pub(crate) fn first(&self) -> Option<&TermWriteResult> {
pub(crate) fn first(&self) -> Option<&Term> {
self.predicates.first()
}
@@ -416,7 +400,7 @@ impl<'a> LoadState<'a> for BootstrappingLoadState<'a> {
#[inline(always)]
fn machine_st(loader: &mut Self::LoaderFieldType) -> &mut MachineState {
loader.term_stream.lexer_parser.machine_st
loader.term_stream.parser.lexer.machine_st
}
#[inline(always)]
@@ -508,9 +492,11 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
}
}
#[inline]
pub(super) fn machine_heap(&mut self) -> &mut Heap {
&mut LS::machine_st(&mut self.payload).heap
pub(crate) fn read_term_from_heap(&mut self, r: RegType) -> Term {
let machine_st = LS::machine_st(&mut self.payload);
let cell = machine_st[r];
machine_st.read_term_from_heap(cell)
}
pub(crate) fn load(mut self) -> Result<LS::Evacuable, SessionError> {
@@ -527,30 +513,18 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
let compilation_target = &load_state.compilation_target;
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 term = load_state.term_stream.next(&composite_op_dir)?;
let machine_st = LS::machine_st(&mut self.payload);
let term_key_opt = clause_predicate_key(&machine_st.heap, term.focus);
if !term.is_consistent(&load_state.predicates) {
self.compile_and_submit()?;
}
if let Some(predicate_focus) = predicate_focus_opt {
let predicate_key_opt = clause_predicate_key(&machine_st.heap, predicate_focus);
debug_assert!(predicate_key_opt.is_some());
if term_key_opt != predicate_key_opt {
self.compile_and_submit()?;
let term = match term {
Term::Clause(_, name, terms) if name == atom!(":-") && terms.len() == 1 => {
return Ok(Some(setup_declaration(self, terms)?));
}
}
if Some((atom!(":-"), 1)) == term_key_opt {
let machine_st = LS::machine_st(&mut self.payload);
term.focus = term_nth_arg(&machine_st.heap, term.focus, 1).unwrap();
return Ok(Some(setup_declaration(self, term)?));
}
term => term,
};
self.payload.predicates.push(term);
}
@@ -788,7 +762,7 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
) => {
remove_constant_indices(
constant,
&overlapping_constants,
overlapping_constants,
indexing_code,
clause_loc - index_loc, // WAS: &inner_index_locs,
);
@@ -1071,73 +1045,30 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
let machine_st = LS::machine_st(&mut self.payload);
let cell = machine_st[r];
let focus = machine_st.heap.cell_len();
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 = machine_st.read_term_from_heap(cell);
let export_list = setup_module_export_list(export_list)?;
Ok(export_list.into_iter().collect())
}
fn clause_clause(&mut self, cell: HeapCellValue) -> Result<TermWriteResult, CompilationError> {
let machine_st = LS::machine_st(&mut self.payload);
let focus = machine_st.heap.cell_len();
fn add_clause_clause(&mut self, term: Term) -> Result<(), CompilationError> {
match term {
Term::Clause(_, atom!(":-"), mut terms) if terms.len() == 2 => {
let body = terms.pop().unwrap();
let head = terms.pop().unwrap();
read_heap_cell!(cell,
(HeapCellValueTag::Str, s) => {
let (name, arity) = cell_as_atom_cell!(machine_st.heap[s])
.get_name_and_arity();
let mut writer = machine_st.heap.reserve(4)
.map_err(|_err_loc| ParserError::ResourceError(ParserErrorSrc::default()))?;
writer.write_with(|section| {
section.push_cell(str_loc_as_cell!(focus+1));
section.push_cell(atom_as_cell!(atom!("clause"), 2));
match (name, arity) {
(atom!(":-"), 2) => {
section.push_cell(heap_loc_as_cell!(s+1));
section.push_cell(heap_loc_as_cell!(s+2));
}
_ => {
section.push_cell(str_loc_as_cell!(s));
section.push_cell(atom_as_cell!(atom!("true")));
}
}
});
self.payload.clause_clauses.push((head, body));
}
(HeapCellValueTag::Atom, (name, arity)) => {
if arity == 0 {
let mut writer = machine_st.heap.reserve(4)
.map_err(|_err_loc| ParserError::ResourceError(ParserErrorSrc::default()))?;
writer.write_with(|section| {
section.push_cell(str_loc_as_cell!(focus+1));
section.push_cell(atom_as_cell!(atom!("clause"), 2));
section.push_cell(atom_as_cell!(name));
section.push_cell(atom_as_cell!(atom!("true")));
});
} else {
return Err(CompilationError::InadmissibleFact);
}
head @ (Term::Clause(..) | Term::Literal(_, Literal::Atom(_))) => {
let body = Term::Literal(Cell::default(), Literal::Atom(atom!("true")));
self.payload.clause_clauses.push((head, body));
}
_ => {
return Err(CompilationError::InadmissibleFact);
}
);
}
Ok(
TermWriteResult::from(&mut machine_st.heap, heap_loc_as_cell!(focus))
.map_err(|_err_loc| ParserError::ResourceError(ParserErrorSrc::default()))?,
)
Ok(())
}
fn add_extensible_predicate_declaration(
@@ -1355,11 +1286,9 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
)
}
fn add_clause_clause_if_dynamic(&mut self, value: HeapCellValue) -> Result<(), SessionError> {
let machine_st = LS::machine_st(&mut self.payload);
let key_opt = clause_predicate_key_from_heap(&machine_st.heap, value);
if let Some((predicate_name, predicate_arity)) = key_opt {
fn add_clause_clause_if_dynamic(&mut self, term: &Term) -> Result<(), SessionError> {
if let Some(predicate_name) = ClauseInfo::name(term) {
let predicate_arity = ClauseInfo::arity(term);
let predicates_compilation_target = self.payload.predicates.compilation_target;
let is_dynamic = self
@@ -1373,8 +1302,7 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
.unwrap_or(false);
if is_dynamic {
let clause_clause_term = self.clause_clause(value)?;
self.payload.clause_clauses.push(clause_clause_term);
self.add_clause_clause(term.clone())?;
}
}
@@ -1440,6 +1368,90 @@ impl<'a> MachinePreludeView<'a> {
}
}
impl MachineState {
pub(super) fn read_term_from_heap(&mut self, term_addr: HeapCellValue) -> Term {
let mut term_stack = vec![];
self.heap[0] = term_addr;
let mut iter =
stackful_post_order_iter::<NonListElider>(&mut self.heap, &mut self.stack, 0);
while let Some(addr) = iter.next() {
let addr = unmark_cell_bits!(addr);
if let Ok(literal) = Literal::try_from(addr) {
term_stack.push(Term::Literal(Cell::default(), literal));
} else {
read_heap_cell!(addr,
(HeapCellValueTag::Lis) => {
use crate::parser::parser::as_partial_string;
let tail = term_stack.pop().unwrap();
let head = term_stack.pop().unwrap();
match as_partial_string(head, tail) {
Ok((string, Some(tail))) => {
term_stack.push(Term::PartialString(Cell::default(), Rc::new(string), tail));
}
Ok((string, None)) => {
term_stack.push(Term::CompleteString(Cell::default(), Rc::new(string)));
}
Err(cons_term) => term_stack.push(cons_term),
}
}
(HeapCellValueTag::StackVar, h) => {
term_stack.push(Term::Var(Cell::default(), VarPtr::from(format!("s_{}", h))));
}
(HeapCellValueTag::Var | HeapCellValueTag::AttrVar, h) => {
term_stack.push(Term::Var(Cell::default(), VarPtr::from(format!("_{}", h))));
}
(HeapCellValueTag::Atom, (name, arity)) => {
let h = iter.focus().value() as usize;
let mut arity = arity;
let value = iter.heap[h.saturating_sub(1)];
if let Some(idx) = get_structure_index(value) {
term_stack.push(Term::Literal(Cell::default(), Literal::CodeIndex(idx)));
arity += 1;
}
if arity == 0 {
term_stack.push(Term::Literal(Cell::default(), Literal::Atom(name)));
} else {
let subterms = term_stack
.drain(term_stack.len() - arity ..)
.collect();
term_stack.push(Term::Clause(Cell::default(), name, subterms));
}
}
(HeapCellValueTag::PStrLoc, h) => {
let HeapStringScan { string, .. } = iter.heap.scan_slice_to_str(h);
let tail = term_stack.pop().unwrap();
term_stack.push(if matches!(tail, Term::Literal(_, Literal::Atom(atom!("[]")))) {
Term::CompleteString(
Cell::default(),
Rc::new(string.to_owned()),
)
} else {
Term::PartialString(
Cell::default(),
Rc::new(string.to_owned()),
Box::new(tail),
)
});
}
_ => {
}
);
}
}
debug_assert!(term_stack.len() == 1);
term_stack.pop().unwrap()
}
}
impl Machine {
pub(crate) fn use_module(&mut self) -> CallResult {
let subevacuable_addr = self
@@ -1600,15 +1612,11 @@ impl Machine {
}
pub(crate) fn add_term_expansion_clause(&mut self) -> CallResult {
let value = self.machine_st.registers[1];
let term = resource_error_call_result!(
self.machine_st,
TermWriteResult::from(&mut self.machine_st.heap, value)
);
let mut loader = self.loader_from_heap_evacuable(temp_v!(2));
let add_clause = || {
let term = loader.read_term_from_heap(temp_v!(1));
loader.incremental_compile_clause(
(atom!("term_expansion"), 2),
term,
@@ -1629,37 +1637,30 @@ impl Machine {
.machine_st
.store(self.machine_st.deref(self.machine_st.registers[1])));
let mut loader = self.loader_from_heap_evacuable(temp_v!(3));
let compilation_target = match target_module_name {
atom!("user") => CompilationTarget::User,
_ => CompilationTarget::Module(target_module_name),
};
let value = self.machine_st.registers[2];
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(_) => term_nth_arg(&self.machine_st.heap, term.focus, 1),
let term = loader.read_term_from_heap(temp_v!(2));
let indexing_arg = match term.name() {
Some(atom!(":-")) => term.first_arg().and_then(Term::first_arg),
Some(_) => term.first_arg(),
None => None,
};
let key_opt = indexing_arg_opt.and_then(|indexing_term_loc| {
term_predicate_key(&self.machine_st.heap, indexing_term_loc)
});
let mut loader = self.loader_from_heap_evacuable(temp_v!(3));
if let Some((name, arity)) = key_opt {
loader
.wam_prelude
.indices
.goal_expansion_indices
.insert((name, arity));
if let Some(indexing_term) = indexing_arg {
if let Some(indexing_name) = indexing_term.name() {
loader
.wam_prelude
.indices
.goal_expansion_indices
.insert((indexing_name, indexing_term.arity()));
}
}
loader.incremental_compile_clause(
@@ -1964,21 +1965,29 @@ impl Machine {
};
let stub_gen = || functor_stub(key.0, key.1);
let assert_clause = self.machine_st.registers[2];
let key_opt = clause_predicate_key_from_heap(&self.machine_st.heap, assert_clause);
let head = self.deref_register(2);
let mut compile_assert = |assert_clause, key_opt| {
if head.is_var() {
let err = self.machine_st.instantiation_error();
return Err(self.machine_st.error_form(err, stub_gen()));
}
let mut compile_assert = || {
let mut loader: Loader<'_, LiveLoadAndMachineState<'_>> =
Loader::new(self, LiveTermStream::new(ListingSource::User));
loader.payload.compilation_target = compilation_target;
let (name, arity) = if let Some(key) = key_opt {
key
let head =
LiveLoadAndMachineState::machine_st(&mut loader.payload).read_term_from_heap(head);
let name = if let Some(name) = head.name() {
name
} else {
return Err(SessionError::from(CompilationError::InvalidRuleHead));
};
let arity = head.arity();
let is_builtin = loader.wam_prelude.indices.builtin_property((name, arity));
let is_dynamic_predicate = loader
@@ -2010,39 +2019,39 @@ impl Machine {
return LiveLoadAndMachineState::evacuate(loader);
}
let body = loader.read_term_from_heap(temp_v!(3));
let asserted_clause = Term::Clause(
Cell::default(),
atom!(":-"),
vec![head.clone(), body.clone()],
);
// if a new predicate was just created, make it dynamic.
loader.add_dynamic_predicate(compilation_target, name, arity)?;
let machine_st = LiveLoadAndMachineState::machine_st(&mut loader.payload);
// let asserted_clause = loader.copy_term_from_heap(assert_clause);
let term = TermWriteResult::from(&mut machine_st.heap, assert_clause)
.map_err(|_err_loc| ParserError::ResourceError(ParserErrorSrc::default()))?;
loader.incremental_compile_clause(
(name, arity),
term,
asserted_clause,
compilation_target,
false,
append_or_prepend,
)?;
let clause_clause_term = loader.clause_clause(assert_clause)?;
// the global clock is incremented after each assertion.
LiveLoadAndMachineState::machine_st(&mut loader.payload).global_clock += 1;
loader.compile_clause_clauses(
(name, arity),
compilation_target,
vec![clause_clause_term],
std::iter::once((head, body)),
append_or_prepend,
)?;
LiveLoadAndMachineState::evacuate(loader)
};
match compile_assert(assert_clause, key_opt) {
match compile_assert() {
Ok(_) => Ok(()),
Err(SessionError::CompilationError(
CompilationError::InvalidRuleHead | CompilationError::InadmissibleFact,
@@ -2244,23 +2253,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 is_consistent = if let Some(predicate_focus) = predicate_focus_opt {
let machine_st = LiveLoadAndMachineState::machine_st(&mut loader.payload);
clause_predicate_key(&machine_st.heap, predicate_focus) == Some(key)
} else {
true
};
LiveLoadAndMachineState::machine_st(&mut loader.payload).fail =
(!loader.payload.predicates.is_empty()
&& loader.payload.predicates.compilation_target != compilation_target)
|| !is_consistent;
|| !key.is_consistent(&loader.payload.predicates);
let result = LiveLoadAndMachineState::evacuate(loader);
self.restore_load_state_payload(result)
@@ -2467,17 +2464,11 @@ impl<'a> Loader<'a, LiveLoadAndMachineState<'a>> {
self.payload.predicates.compilation_target = compilation_target;
}
let machine_st = LiveLoadAndMachineState::machine_st(&mut self.payload);
let value = machine_st.store(MachineState::deref(machine_st, machine_st[term_reg]));
self.add_clause_clause_if_dynamic(value)?;
let machine_st = LiveLoadAndMachineState::machine_st(&mut self.payload);
let term = TermWriteResult::from(&mut machine_st.heap, value)
.map_err(|_err_loc| ParserError::ResourceError(ParserErrorSrc::default()))?;
let term = self.read_term_from_heap(term_reg);
self.add_clause_clause_if_dynamic(&term)?;
self.payload.term_stream.term_queue.push_back(term);
self.load()
}
}

View File

@@ -19,7 +19,7 @@ pub type MachineStubGen = Box<dyn Fn(&mut MachineState) -> MachineStub>;
#[derive(Debug)]
pub(crate) struct MachineError {
stub: MachineStub,
location: Option<ParserErrorSrc>,
location: Option<(usize, usize)>, // line_num, col_num
}
// from 7.12.2 b) of 13211-1:1995
@@ -301,7 +301,7 @@ impl MachineState {
}
}
pub(super) fn resource_error(&mut self, err: ResourceError) -> MachineError {
pub(super) fn resource_error(err: ResourceError) -> MachineError {
let stub = match err {
ResourceError::FiniteMemory(size_requested) => {
functor!(
@@ -466,10 +466,10 @@ impl MachineState {
fn arithmetic_error(&mut self, err: ArithmeticError) -> MachineError {
match err {
ArithmeticError::NonEvaluableFunctor(cell, arity) => {
let culprit = functor!(atom!("/"), [cell(cell), fixnum(arity)]);
let culprit = functor!(atom!("/"), [literal(cell), fixnum(arity)]);
self.type_error(ValidType::Evaluable, culprit)
}
ArithmeticError::UninstantiatedVar => self.instantiation_error(),
}
}
@@ -609,7 +609,7 @@ impl MachineState {
}
pub(super) fn error_form(&mut self, err: MachineError, src: MachineStub) -> MachineStub {
if let Some(ParserErrorSrc { line_num, .. }) = err.location {
if let Some((line_num, _col_num)) = err.location {
functor!(
atom!("error"),
[
@@ -665,16 +665,17 @@ pub enum CompilationError {
InvalidRuleHead,
InvalidUseModuleDecl,
InvalidModuleResolution(Atom),
FiniteMemoryInHeap(usize),
}
#[derive(Debug)]
pub enum DirectiveError {
ExpectedDirective(HeapCellValue),
ExpectedDirective(Term),
InvalidDirective(Atom, usize /* arity */),
InvalidOpDeclNameType(HeapCellValue),
InvalidOpDeclSpecDomain(HeapCellValue),
InvalidOpDeclNameType(Term),
InvalidOpDeclSpecDomain(Term),
InvalidOpDeclSpecValue(Atom),
InvalidOpDeclPrecType(HeapCellValue),
InvalidOpDeclPrecType(Term),
InvalidOpDeclPrecDomain(Fixnum),
ShallNotCreate(Atom),
ShallNotModify(Atom),
@@ -695,9 +696,9 @@ impl From<ParserError> for CompilationError {
}
impl CompilationError {
pub(crate) fn line_and_col_num(&self) -> Option<ParserErrorSrc> {
pub(crate) fn line_and_col_num(&self) -> Option<(usize, usize)> {
match self {
CompilationError::ParserError(err) => Some(err.err_src()),
CompilationError::ParserError(err) => err.line_and_col_num(),
_ => None,
}
}
@@ -740,6 +741,9 @@ impl CompilationError {
CompilationError::ParserError(ref err) => {
functor!(err.as_atom())
}
CompilationError::FiniteMemoryInHeap(h) => {
vec![FunctorElement::AbsoluteCell(str_loc_as_cell!(*h))]
}
}
}
}
@@ -1015,6 +1019,13 @@ pub enum SessionError {
PredicateNotMultifileOrDiscontiguous(CompilationTarget, PredicateKey),
}
impl From<std::io::Error> for SessionError {
#[inline]
fn from(err: std::io::Error) -> SessionError {
SessionError::from(ParserError::from(err))
}
}
impl From<ParserError> for SessionError {
#[inline]
fn from(err: ParserError) -> Self {

View File

@@ -21,8 +21,6 @@ use std::collections::BTreeSet;
use std::ops::{Deref, DerefMut};
use crate::types::*;
// #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
// pub(crate) struct OrderedOpDirKey(pub(crate) Atom, pub(crate) Fixity);
// 7.2
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
@@ -223,6 +221,30 @@ impl CodeIndex {
*/
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum VarKey {
AnonVar(usize),
VarPtr(VarPtr),
}
impl VarKey {
#[allow(clippy::inherent_to_string)]
#[inline]
pub(crate) fn to_string(&self) -> String {
match self {
VarKey::AnonVar(h) => format!("_{}", h),
VarKey::VarPtr(var) => var.borrow().to_string(),
}
}
#[inline(always)]
pub(crate) fn is_anon(&self) -> bool {
matches!(self, VarKey::AnonVar(_))
}
}
pub(crate) type HeapVarDict = IndexMap<VarKey, HeapCellValue, FxBuildHasher>;
pub(crate) type GlobalVarDir = IndexMap<Atom, (Ball, Option<HeapCellValue>), FxBuildHasher>;
pub(crate) type StreamAliasDir = IndexMap<Atom, Stream, FxBuildHasher>;
@@ -279,9 +301,11 @@ impl IndexStore {
_ => self
.get_meta_predicate_spec(key.0, key.1, &compilation_target)
.map(|meta_specs| {
meta_specs.iter().find(|meta_spec| match meta_spec {
MetaSpec::Colon | MetaSpec::RequiresExpansionWithArgument(_) => true,
_ => false,
meta_specs.iter().find(|meta_spec| {
matches!(
meta_spec,
MetaSpec::Colon | MetaSpec::RequiresExpansionWithArgument(_)
)
})
})
.map(|meta_spec_opt| meta_spec_opt.is_some())

View File

@@ -13,6 +13,7 @@ use crate::machine::stack::*;
use crate::machine::streams::*;
use crate::machine::Machine;
use crate::parser::ast::*;
use crate::read::TermWriteResult;
use crate::types::*;
use crate::parser::dashu::Integer;
@@ -22,7 +23,6 @@ use indexmap::IndexMap;
use std::convert::TryFrom;
use std::fmt;
use std::ops::{Index, IndexMut, Range};
use std::rc::Rc;
use std::sync::Arc;
pub(crate) type Registers = [HeapCellValue; MAX_ARITY + 1];
@@ -72,7 +72,7 @@ pub struct MachineState {
pub(super) e: usize,
pub(super) num_of_args: usize,
pub(super) cp: usize,
pub(crate) attr_var_init: AttrVarInitializer,
pub(super) attr_var_init: AttrVarInitializer,
pub(super) fail: bool,
pub heap: Heap,
pub(super) mode: MachineMode,
@@ -203,52 +203,56 @@ pub fn pstr_loc_and_offset(heap: &[HeapCellValue], index: usize) -> (usize, Fixn
}
*/
fn push_var_eq_functors(
// size may be an upper bound.
// true_size is calculated to compute the exact offset.
fn push_var_eq_functors<'a>(
heap: &mut Heap,
size: usize,
iter: impl Iterator<Item = (usize, Var)>,
iter: impl Iterator<Item = (&'a VarKey, &'a HeapCellValue)>,
atom_tbl: &AtomTable,
) -> Result<HeapCellValue, usize> {
let src_h = heap.cell_len();
if size > 0 {
let mut writer = heap.reserve(1 + 5 * size)?;
let true_size = if size > 0 {
let mut writer = heap.reserve(2 + 5 * size)?;
writer.write_with(|section| {
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);
writer
.write_with(|section| {
let mut size = 0;
section.push_cell(atom_as_cell!(atom!("="), 2));
section.push_cell(atom_as_cell!(var_atom));
section.push_cell(binding);
}
for (var, binding) in iter {
let var_atom = AtomTable::build_with(atom_tbl, &var.to_string());
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));
}
section.push_cell(atom_as_cell!(atom!("="), 2));
section.push_cell(atom_as_cell!(var_atom));
section.push_cell(*binding);
section.push_cell(empty_list_as_cell!());
});
size += 1;
}
Ok(heap_loc_as_cell!(src_h + 3 * 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));
}
if size > 0 {
section.push_cell(empty_list_as_cell!());
}
size
})
.result
} else {
Ok(empty_list_as_cell!())
}
}
size
};
/*
pub(crate) fn copy_and_align_iter<Iter: Iterator<Item = HeapCellValue>>(
iter: Iter,
boundary: i64,
h: i64,
) -> impl Iterator<Item = HeapCellValue> {
let diff = boundary - h;
iter.map(move |heap_value| heap_value - diff)
Ok(if true_size > 0 {
heap_loc_as_cell!(src_h + 3 * true_size)
} else {
empty_list_as_cell!()
})
}
*/
#[derive(Debug)]
pub struct Ball {
@@ -377,7 +381,7 @@ impl<'a> CopierTarget for CopyTerm<'a> {
}
#[derive(Debug)]
pub(crate) struct CopyBallTerm<'a> {
pub(super) struct CopyBallTerm<'a> {
attr_var_queue: &'a mut Vec<usize>,
stack: &'a mut Stack,
heap: &'a mut Heap,
@@ -385,7 +389,7 @@ pub(crate) struct CopyBallTerm<'a> {
}
impl<'a> CopyBallTerm<'a> {
pub(crate) fn new(
pub(super) fn new(
attr_var_queue: &'a mut Vec<usize>,
stack: &'a mut Stack,
heap: &'a mut Heap,
@@ -629,24 +633,13 @@ impl MachineState {
pub fn write_read_term_options(
&mut self,
mut var_list: Vec<(Var, HeapCellValue, usize)>,
singletons_heap_list: HeapCellValue,
mut var_list: Vec<(VarKey, HeapCellValue, usize)>,
singleton_heap_list: HeapCellValue,
) -> CallResult {
var_list.sort_by(|(_, _, idx_1), (_, _, idx_2)| idx_1.cmp(idx_2));
/*
let list_of_var_eqs = push_var_eq_functors(
&mut self.heap,
var_list.iter().map(|(var_name, var, _)| {
(var.get_value() as usize, var_name.clone())
}),
num_vars,
&self.atom_tbl,
);
*/
let singleton_addr = self.registers[3];
unify_fn!(*self, singletons_heap_list, singleton_addr);
unify_fn!(*self, singleton_heap_list, singleton_addr);
if self.fail {
return Ok(());
@@ -669,21 +662,18 @@ impl MachineState {
}
let var_names_addr = self.registers[5];
/*
let var_names_offset = heap_loc_as_cell!(iter_to_heap_list(
&mut self.heap,
list_of_var_eqs.into_iter()
));
*/
let var_names_offset = resource_error_call_result!(
self,
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().filter_map(|(var_name, var, _)| {
if var_name.is_anon() {
None
} else {
Some((var_name, var))
}
}),
&self.atom_tbl,
)
);
@@ -691,37 +681,22 @@ impl MachineState {
Ok(unify_fn!(*self, var_names_offset, var_names_addr))
}
pub fn read_term_body(&mut self, term: TermWriteResult) -> CallResult {
let heap_loc = self.heap[term.focus];
/*
read_heap_cell!(self.heap[term.heap_loc],
(HeapCellValueTag::PStr) => { // | HeapCellValueTag::PStrOffset) => {
pstr_loc_as_cell!(term.heap_loc)
}
_ => {
heap_loc_as_cell!(term.heap_loc)
}
);
*/
pub fn read_term_body(&mut self, mut term_write_result: TermWriteResult) -> CallResult {
let heap_loc = heap_loc_as_cell!(term_write_result.heap_loc);
unify_fn!(*self, heap_loc, self.registers[2]);
if self.fail {
return Ok(());
}
/*
for var in term_write_result.var_dict.values_mut() {
*var = heap_bound_deref(&self.heap, *var);
}
*/
let mut singleton_var_set: IndexMap<Ref, bool> = IndexMap::new();
self.heap[0] = heap_loc;
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, 0) {
let cell = unmark_cell_bits!(cell);
if let Some(var) = cell.as_var() {
@@ -737,38 +712,36 @@ impl MachineState {
self,
push_var_eq_functors(
&mut self.heap,
singleton_var_set
term_write_result.var_dict.len(),
term_write_result
.var_dict
.iter()
.filter(|(var, is_singleton)| {
**is_singleton
&& term
.inverse_var_locs
.contains_key(&(var.get_value() as usize))
})
.count(),
term.inverse_var_locs
.iter()
.filter_map(|(var_loc, var_name)| {
let r = Ref::heap_cell(*var_loc);
.filter(|(var_name, binding)| {
if var_name.is_anon() {
return false;
}
if singleton_var_set.get(&r).cloned().unwrap_or(false) {
Some((*var_loc, var_name.clone()))
if let Some(r) = binding.as_var() {
*singleton_var_set.get(&r).unwrap_or(&false)
} else {
None
false
}
}),
&self.atom_tbl,
)
);
for var in term_write_result.var_dict.values_mut() {
*var = heap_bound_deref(&self.heap, *var);
}
let mut var_list = Vec::with_capacity(singleton_var_set.len());
for (var_loc, var_name) in term.inverse_var_locs {
let r = Ref::heap_cell(var_loc);
let cell = self.heap[var_loc];
if let Some(idx) = singleton_var_set.get_index_of(&r) {
var_list.push((var_name, cell, idx));
for (var_name, addr) in term_write_result.var_dict {
if let Some(var) = addr.as_var() {
if let Some(idx) = singleton_var_set.get_index_of(&var) {
var_list.push((var_name, addr, idx));
}
}
}
@@ -851,8 +824,8 @@ impl MachineState {
}
loop {
match self.read_to_heap(stream, &indices.op_dir) {
Ok(term) => return self.read_term_body(term),
match self.read(stream, &indices.op_dir) {
Ok(term_write_result) => return self.read_term_body(term_write_result),
Err(err) => {
match &err {
CompilationError::ParserError(e) if e.is_unexpected_eof() => {
@@ -891,7 +864,7 @@ impl MachineState {
let printer = match self.try_from_list(self.registers[6], stub_gen) {
Ok(addrs) => {
let mut var_names: IndexMap<HeapCellValue, Var> = IndexMap::new();
let mut var_names: IndexMap<HeapCellValue, VarPtr> = IndexMap::new();
for addr in addrs {
read_heap_cell!(addr,
@@ -910,14 +883,14 @@ impl MachineState {
read_heap_cell!(atom,
(HeapCellValueTag::Atom, (name, _arity)) => {
debug_assert_eq!(_arity, 0);
var_names.insert(var, Rc::new(name.as_str().to_owned()));
var_names.insert(var, VarPtr::from(name.as_str().to_owned()));
}
(HeapCellValueTag::Str, s) => {
let (name, arity) = cell_as_atom_cell!(self.heap[s])
.get_name_and_arity();
debug_assert_eq!(arity, 0);
var_names.insert(var, Rc::new(name.as_str().to_owned()));
var_names.insert(var, VarPtr::from(name.as_str().to_owned()));
}
_ => {
unreachable!();
@@ -996,18 +969,14 @@ 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);
});
self.heap[0] = term_to_be_printed;
let mut printer = HCPrinter::new(
&mut self.heap,
&mut self.stack,
op_dir,
PrinterOutputter::new(),
term_loc,
0,
);
printer.ignore_ops = ignore_ops;
@@ -1040,7 +1009,6 @@ impl MachineState {
}
printer.var_names = var_names;
printer
}
Err(err) => {

View File

@@ -621,10 +621,17 @@ impl MachineState {
(HeapCellValueTag::PStrLoc, l1) => {
read_heap_cell!(v2,
(HeapCellValueTag::PStrLoc, l2) => {
let cmp_result = self.heap.compare_pstr_segments(l1, l2);
if let Some(ordering) = cmp_result.continue_pstr_compare(&mut self.pdl) {
return Some(ordering);
match self.heap.compare_pstr_segments(l1, l2) {
PStrSegmentCmpResult::Continue(v1, v2) => {
self.pdl.push(v1);
self.pdl.push(v2);
}
PStrSegmentCmpResult::Less => {
return Some(Ordering::Less);
}
PStrSegmentCmpResult::Greater => {
return Some(Ordering::Greater);
}
}
}
(HeapCellValueTag::Lis, l2) => {
@@ -747,38 +754,6 @@ impl MachineState {
Some(Ordering::Equal)
}
/* TODO: new, inlined match_partial_string. now inlined into GetPartialString,
* the only place it is called from. Therefore, it has been inlined.
pub fn match_partial_string(
&mut self,
value: HeapCellValue,
string: &str,
) -> Result<(), usize> {
debug_assert!(value.is_ref());
self.heap[0] = value;
let mut heap_pstr_iter = HeapPStrIter::new(&self.heap, 0);
match heap_pstr_iter.compare_pstr_to_string(string) {
Some(PStrCmpResult::CompleteMatch { bytes_matched, pstr_loc }) => {
self.s_offset = bytes_matched;
self.s = HeapPtr::PStr(pstr_loc);
self.mode = MachineMode::Read;
}
Some(PStrCmpResult::PartialMatch { string, var_loc }) => {
let cell = self.heap.allocate_pstr(string)?;
unify!(self, cell, heap_loc_as_loc!(var_loc));
}
None => {
self.fail = true;
}
}
Ok(())
}
*/
pub(crate) fn setup_call_n_init_goal_info(
&mut self,
goal: HeapCellValue,

View File

@@ -7,6 +7,7 @@ pub use crate::parser::ast::*;
#[cfg(test)]
use crate::machine::copier::CopierTarget;
use crate::read::TermWriteResult;
#[cfg(test)]
use std::ops::{Deref, DerefMut, Index, IndexMut, Range};
@@ -34,7 +35,7 @@ impl MockWAM {
&mut self,
input_stream: Stream,
) -> Result<TermWriteResult, CompilationError> {
self.machine_st.read_to_heap(input_stream, &self.op_dir)
self.machine_st.read(input_stream, &self.op_dir)
}
pub fn parse_and_write_parsed_term_to_heap(
@@ -50,24 +51,24 @@ impl MockWAM {
term_string: &'static str,
) -> Result<String, CompilationError> {
let term_write_result = self.parse_and_write_parsed_term_to_heap(term_string)?;
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()))
.collect();
print_heap_terms(&self.machine_st.heap, term_write_result.heap_loc);
let mut printer = HCPrinter::new(
&mut self.machine_st.heap,
&mut self.machine_st.stack,
&self.op_dir,
PrinterOutputter::new(),
term_write_result.focus,
term_write_result.heap_loc,
);
printer.var_names = var_names;
printer.var_names = term_write_result
.var_dict
.into_iter()
.map(|(var, cell)| match var {
VarKey::VarPtr(var) => (cell, var.clone()),
VarKey::AnonVar(_) => (cell, VarPtr::from(var.to_string())),
})
.collect();
Ok(printer.print().result())
}
@@ -238,7 +239,7 @@ pub(crate) fn write_parsed_term_to_heap(
input_stream: Stream,
op_dir: &OpDir,
) -> Result<TermWriteResult, CompilationError> {
machine_st.read_to_heap(input_stream, op_dir)
machine_st.read(input_stream, op_dir)
}
#[cfg(test)]
@@ -298,7 +299,7 @@ mod tests {
unify!(
wam,
str_loc_as_cell!(0),
str_loc_as_cell!(term_write_result_2.focus)
str_loc_as_cell!(term_write_result_2.heap_loc)
);
assert!(wam.fail);
@@ -310,16 +311,15 @@ mod tests {
wam.heap.clear();
{
let term_write_result_1 =
parse_and_write_parsed_term_to_heap(&mut wam, "f(X,X).", &op_dir).unwrap();
parse_and_write_parsed_term_to_heap(&mut wam, "f(X,X).", &op_dir).unwrap();
let term_write_result_2 =
parse_and_write_parsed_term_to_heap(&mut wam, "f(b,b).", &op_dir).unwrap();
unify!(
wam,
heap_loc_as_cell!(term_write_result_1.focus),
heap_loc_as_cell!(term_write_result_2.focus)
str_loc_as_cell!(1),
heap_loc_as_cell!(term_write_result_2.heap_loc)
);
assert!(!wam.fail);
@@ -331,16 +331,15 @@ mod tests {
wam.heap.clear();
{
let term_write_result_1 =
parse_and_write_parsed_term_to_heap(&mut wam, "f(X,X).", &op_dir).unwrap();
parse_and_write_parsed_term_to_heap(&mut wam, "f(X,X).", &op_dir).unwrap();
let term_write_result_2 =
parse_and_write_parsed_term_to_heap(&mut wam, "f(f(A),Y).", &op_dir).unwrap();
unify!(
wam,
heap_loc_as_cell!(term_write_result_1.focus),
heap_loc_as_cell!(term_write_result_2.focus)
heap_loc_as_cell!(0),
heap_loc_as_cell!(term_write_result_2.heap_loc)
);
assert!(!wam.fail);
@@ -352,16 +351,15 @@ mod tests {
wam.heap.clear();
{
let term_write_result_1 =
parse_and_write_parsed_term_to_heap(&mut wam, "f(X,X).", &op_dir).unwrap();
parse_and_write_parsed_term_to_heap(&mut wam, "f(X,X).", &op_dir).unwrap();
let term_write_result_2 =
parse_and_write_parsed_term_to_heap(&mut wam, "f(f(A),Y).", &op_dir).unwrap();
unify!(
wam,
heap_loc_as_cell!(term_write_result_1.focus),
heap_loc_as_cell!(term_write_result_2.focus)
heap_loc_as_cell!(0),
heap_loc_as_cell!(term_write_result_2.heap_loc)
);
assert!(!wam.fail);
@@ -373,16 +371,15 @@ mod tests {
wam.heap.clear();
{
let term_write_result_1 =
parse_and_write_parsed_term_to_heap(&mut wam, "f(X,X).", &op_dir).unwrap();
parse_and_write_parsed_term_to_heap(&mut wam, "f(X,X).", &op_dir).unwrap();
let term_write_result_2 =
parse_and_write_parsed_term_to_heap(&mut wam, "f(f(A),A).", &op_dir).unwrap();
unify!(
wam,
heap_loc_as_cell!(term_write_result_1.focus),
heap_loc_as_cell!(term_write_result_2.focus)
heap_loc_as_cell!(0),
heap_loc_as_cell!(term_write_result_2.heap_loc)
);
assert!(!wam.fail);
@@ -394,8 +391,7 @@ mod tests {
wam.heap.clear();
{
let term_write_result_1 =
parse_and_write_parsed_term_to_heap(&mut wam, "f(X,X).", &op_dir).unwrap();
parse_and_write_parsed_term_to_heap(&mut wam, "f(X,X).", &op_dir).unwrap();
let term_write_result_2 =
parse_and_write_parsed_term_to_heap(&mut wam, "f(A,f(A)).", &op_dir).unwrap();
@@ -404,8 +400,8 @@ mod tests {
unify!(
wam,
heap_loc_as_cell!(term_write_result_1.focus),
heap_loc_as_cell!(term_write_result_2.focus)
heap_loc_as_cell!(0),
heap_loc_as_cell!(term_write_result_2.heap_loc)
);
assert!(!wam.fail);
@@ -526,8 +522,21 @@ mod tests {
});
unify!(wam, heap_loc_as_cell!(0), heap_loc_as_cell!(5));
assert!(!wam.fail);
all_cells_unmarked(&wam.heap);
wam.heap.clear();
{
let term_write_result_1 =
parse_and_write_parsed_term_to_heap(&mut wam, "X = g(X,y).", &op_dir).unwrap();
print_heap_terms(&wam.heap, term_write_result_1.heap_loc);
unify!(wam, heap_loc_as_cell!(2), str_loc_as_cell!(4));
assert_eq!(wam.heap[2], str_loc_as_cell!(4));
}
}
#[test]
@@ -550,8 +559,8 @@ mod tests {
unify_with_occurs_check!(
wam,
heap_loc_as_cell!(0),
heap_loc_as_cell!(term_write_result_2.focus)
str_loc_as_cell!(0),
str_loc_as_cell!(term_write_result_2.heap_loc)
);
assert!(wam.fail);
@@ -594,7 +603,7 @@ mod tests {
Some(Ordering::Equal)
);
let cstr_cell = wam.allocate_cstr("string").unwrap();
let cstr_cell = wam.heap.allocate_cstr("string").unwrap();
assert_eq!(
compare_term_test!(wam, atom_as_cell!(atom!("atom")), cstr_cell),
@@ -693,7 +702,7 @@ mod tests {
Some(Ordering::Greater)
);
let cstr_cell = wam.allocate_cstr("string").unwrap();
let cstr_cell = wam.heap.allocate_cstr("string").unwrap();
assert_eq!(
compare_term_test!(wam, empty_list_as_cell!(), cstr_cell),
@@ -782,7 +791,7 @@ mod tests {
wam.heap.clear();
let h = wam.heap.cell_len();
wam.allocate_cstr("a string").unwrap();
wam.heap.allocate_cstr("a string").unwrap();
assert!(!wam.is_cyclic_term(h));
}

View File

@@ -1114,7 +1114,6 @@ 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) {

View File

@@ -363,7 +363,7 @@ mod test {
fn pstr_iter_tests() {
let mut wam = MockWAM::new();
let pstr_cell = wam.machine_st.allocate_pstr("abc ").unwrap();
let pstr_cell = wam.machine_st.heap.allocate_pstr("abc ").unwrap();
wam.machine_st
.heap
.push_cell(empty_list_as_cell!())
@@ -391,7 +391,7 @@ mod test {
wam.machine_st.heap[2] = pstr_loc_as_cell!(heap_index!(3));
wam.machine_st.allocate_pstr("def").unwrap();
wam.machine_st.heap.allocate_pstr("def").unwrap();
let h = wam.machine_st.heap.cell_len();
wam.machine_st.heap.push_cell(heap_loc_as_cell!(h)).unwrap();
@@ -456,7 +456,7 @@ mod test {
wam.machine_st.heap.clear();
let pstr_cell = wam.machine_st.allocate_cstr("abc").unwrap();
let pstr_cell = wam.machine_st.heap.allocate_cstr("abc").unwrap();
let start = wam.machine_st.heap.cell_len();
let mut writer = wam.machine_st.heap.reserve(16).unwrap();
@@ -484,7 +484,7 @@ mod test {
wam.machine_st.heap.clear();
let pstr_cell = wam.machine_st.allocate_cstr("abc").unwrap();
let pstr_cell = wam.machine_st.heap.allocate_cstr("abc").unwrap();
let start = wam.machine_st.heap.cell_len();
let mut writer = wam.machine_st.heap.reserve(16).unwrap();
@@ -515,7 +515,7 @@ mod test {
wam.machine_st.heap.clear();
let pstr_cell = wam.machine_st.allocate_cstr("d").unwrap();
let pstr_cell = wam.machine_st.heap.allocate_cstr("d").unwrap();
let start = wam.machine_st.heap.cell_len();
let mut writer = wam.machine_st.heap.reserve(16).unwrap();
@@ -534,7 +534,7 @@ mod test {
wam.machine_st.heap.clear();
let pstr_cell = wam.machine_st.allocate_cstr("abc").unwrap();
let pstr_cell = wam.machine_st.heap.allocate_cstr("abc").unwrap();
let start = wam.machine_st.heap.cell_len();
let mut writer = wam.machine_st.heap.reserve(16).unwrap();
@@ -564,7 +564,7 @@ mod test {
wam.machine_st.heap.clear();
let pstr_cell = wam.machine_st.allocate_cstr("abcdef").unwrap();
let pstr_cell = wam.machine_st.heap.allocate_cstr("abcdef").unwrap();
let start = wam.machine_st.heap.cell_len();
let mut writer = wam.machine_st.heap.reserve(16).unwrap();
@@ -602,7 +602,7 @@ mod test {
wam.machine_st.heap.clear();
wam.machine_st.allocate_cstr("abc").unwrap();
wam.machine_st.heap.allocate_cstr("abc").unwrap();
let start = wam.machine_st.heap.cell_len();
let mut writer = wam.machine_st.heap.reserve(16).unwrap();
@@ -629,7 +629,7 @@ mod test {
wam.machine_st.heap.clear();
wam.machine_st.allocate_cstr("a ").unwrap();
wam.machine_st.heap.allocate_cstr("a ").unwrap();
let start = wam.machine_st.heap.cell_len();
let mut writer = wam.machine_st.heap.reserve(16).unwrap();
@@ -653,7 +653,7 @@ mod test {
wam.machine_st.heap.clear();
wam.machine_st.allocate_cstr(" a").unwrap();
wam.machine_st.heap.allocate_cstr(" a").unwrap();
let start = wam.machine_st.heap.cell_len();
let mut writer = wam.machine_st.heap.reserve(16).unwrap();
@@ -678,7 +678,7 @@ mod test {
wam.machine_st.heap.clear();
wam.machine_st.allocate_cstr("a b").unwrap();
wam.machine_st.heap.allocate_cstr("a b").unwrap();
let start = wam.machine_st.heap.cell_len();
let mut writer = wam.machine_st.heap.reserve(16).unwrap();
@@ -706,7 +706,7 @@ mod test {
wam.machine_st.heap.clear();
wam.machine_st.allocate_cstr(" a ").unwrap();
wam.machine_st.heap.allocate_cstr(" a ").unwrap();
let start = wam.machine_st.heap.cell_len();
let mut writer = wam.machine_st.heap.reserve(16).unwrap();
@@ -733,7 +733,7 @@ mod test {
wam.machine_st.heap.clear();
wam.machine_st.allocate_cstr(" a bc").unwrap();
wam.machine_st.heap.allocate_cstr(" a bc").unwrap();
let start = wam.machine_st.heap.cell_len();
let mut writer = wam.machine_st.heap.reserve(16).unwrap();
@@ -764,7 +764,7 @@ mod test {
wam.machine_st.heap.clear();
wam.machine_st.allocate_cstr("abc").unwrap();
wam.machine_st.heap.allocate_cstr("abc").unwrap();
let start = wam.machine_st.heap.cell_len();
let mut writer = wam.machine_st.heap.reserve(16).unwrap();
@@ -791,7 +791,7 @@ mod test {
// #2293, test7.
wam.machine_st.heap.clear();
wam.machine_st.allocate_cstr("abcde").unwrap();
wam.machine_st.heap.allocate_cstr("abcde").unwrap();
let start = wam.machine_st.heap.cell_len();
let mut writer = wam.machine_st.heap.reserve(16).unwrap();

View File

@@ -3,17 +3,13 @@ use crate::codegen::CodeGenSettings;
use crate::forms::*;
use crate::instructions::*;
use crate::machine::disjuncts::*;
use crate::machine::heap::*;
use crate::machine::loader::*;
use crate::machine::machine_errors::*;
use crate::machine::CodeIndex;
use crate::parser::ast::*;
use crate::types::*;
use fxhash::FxBuildHasher;
use indexmap::IndexMap;
use indexmap::IndexSet;
use std::cell::Cell;
use std::convert::TryFrom;
pub(crate) fn to_op_decl(prec: u16, spec: OpDeclSpec, name: Atom) -> OpDecl {
OpDecl::new(OpDesc::build_with(prec, spec), name)
@@ -25,47 +21,43 @@ 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) {
Some((name, 0)) => name,
_ => {
fn setup_op_decl(mut terms: Vec<Term>) -> Result<OpDecl, CompilationError> {
// should allow non-partial lists?
let name = match terms.pop().unwrap() {
Term::Literal(_, Literal::Atom(name)) => name,
other => {
return Err(CompilationError::InvalidDirective(
DirectiveError::InvalidOpDeclNameType(term.heap[focus + 3]),
DirectiveError::InvalidOpDeclNameType(other),
));
}
};
let spec = match term_predicate_key(term.heap, focus + 2) {
Some((name, _)) => name,
None => {
let spec = match terms.pop().unwrap() {
Term::Literal(_, Literal::Atom(name)) => name,
other => {
return Err(CompilationError::InvalidDirective(
DirectiveError::InvalidOpDeclSpecDomain(term.heap[focus + 2]),
));
DirectiveError::InvalidOpDeclSpecDomain(other),
))
}
};
let spec = to_op_decl_spec(spec)?;
let prec = term.deref_loc(focus + 1);
let prec = read_heap_cell!(prec,
(HeapCellValueTag::Fixnum, n) => {
match u16::try_from(n.get_num()) {
Ok(n) if n <= 1200 => n,
_ => {
return Err(CompilationError::InvalidDirective(
DirectiveError::InvalidOpDeclPrecDomain(n),
));
}
let prec = match terms.pop().unwrap() {
Term::Literal(_, Literal::Fixnum(bi)) => match u16::try_from(bi.get_num()) {
Ok(n) if n <= 1200 => n,
_ => {
return Err(CompilationError::InvalidDirective(
DirectiveError::InvalidOpDeclPrecDomain(bi),
));
}
}
_ => {
},
other => {
return Err(CompilationError::InvalidDirective(
DirectiveError::InvalidOpDeclPrecType(prec),
DirectiveError::InvalidOpDeclPrecType(other),
));
}
);
};
if name == "[]" || name == "{}" {
return Err(CompilationError::InvalidDirective(
@@ -88,162 +80,129 @@ fn setup_op_decl(term: &FocusedHeapRefMut) -> Result<OpDecl, CompilationError> {
Ok(to_op_decl(prec, spec, name))
}
fn setup_predicate_indicator(term: &FocusedHeapRefMut) -> Result<PredicateKey, CompilationError> {
let key_opt = term_predicate_key(term.heap, term.focus);
fn setup_predicate_indicator(term: &mut Term) -> Result<PredicateKey, CompilationError> {
match term {
Term::Clause(_, slash, ref mut terms)
if (*slash == atom!("/") || *slash == atom!("//")) && terms.len() == 2 =>
{
let arity = terms.pop().unwrap();
let name = terms.pop().unwrap();
if let Some((atom!("/") | atom!("//"), 2)) = key_opt {
let arity_loc = term.nth_arg(term.focus, 2).unwrap();
let arity = match Number::try_from(term.deref_loc(arity_loc)) {
Ok(Number::Fixnum(n)) => usize::try_from(n.get_num()).ok(),
Ok(Number::Integer(n)) => (&*n).try_into().ok(),
_ => None,
}
.ok_or(CompilationError::InvalidModuleExport)?;
let name_loc = term.nth_arg(term.focus, 1).unwrap();
let name = term_predicate_key(term.heap, name_loc)
.map(|(name, _)| name)
let arity = match arity {
Term::Literal(_, Literal::Integer(n)) => (&*n).try_into().ok(),
Term::Literal(_, Literal::Fixnum(n)) => usize::try_from(n.get_num()).ok(),
_ => None,
}
.ok_or(CompilationError::InvalidModuleExport)?;
if matches!(key_opt, Some((atom!("/"), _))) {
Ok((name, arity))
} else {
Ok((name, arity + 2))
let name = match name {
Term::Literal(_, Literal::Atom(name)) => Some(name),
_ => None,
}
.ok_or(CompilationError::InvalidModuleExport)?;
if *slash == atom!("/") {
Ok((name, arity))
} else {
Ok((name, arity + 2))
}
}
} else {
Err(CompilationError::InvalidModuleExport)
_ => Err(CompilationError::InvalidModuleExport),
}
}
fn setup_module_export(term: &FocusedHeapRefMut) -> Result<ModuleExport, CompilationError> {
setup_predicate_indicator(term)
fn setup_module_export(mut term: Term) -> Result<ModuleExport, CompilationError> {
setup_predicate_indicator(&mut term)
.map(ModuleExport::PredicateKey)
.or_else(|_| {
let key_opt = term_predicate_key(term.heap, term.focus);
if let Some((atom!("op"), 3)) = key_opt {
Ok(ModuleExport::OpDecl(setup_op_decl(term)?))
if let Term::Clause(_, name, terms) = term {
if terms.len() == 3 && name == atom!("op") {
Ok(ModuleExport::OpDecl(setup_op_decl(terms)?))
} else {
Err(CompilationError::InvalidModuleDecl)
}
} else {
Err(CompilationError::InvalidModuleDecl)
}
})
}
/* TODO: should be unnecessary now.
pub(crate) fn build_rule_body(vars: &[Term], body_term: Term) -> Term {
let head_term = Term::Clause(Cell::default(), atom!(""), vars.to_vec());
let rule = vec![head_term, body_term];
Term::Clause(Cell::default(), atom!(":-"), rule)
}
*/
pub(super) fn setup_module_export_list(
term: FocusedHeapRefMut,
mut export_list: Term,
) -> Result<Vec<ModuleExport>, CompilationError> {
let mut exports = vec![];
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,
};
while let Term::Cons(_, t1, t2) = export_list {
let module_export = setup_module_export(*t1)?;
exports.push(setup_module_export(&term)?);
focus = l + 1;
}
(HeapCellValueTag::Atom, (name, _arity)) => {
if name == atom!("[]") {
return Ok(exports);
} else {
break;
}
}
_ => {
break;
}
);
exports.push(module_export);
export_list = *t2;
}
Err(CompilationError::InvalidModuleDecl)
if let Term::Literal(_, Literal::Atom(atom!("[]"))) = export_list {
Ok(exports)
} else {
Err(CompilationError::InvalidModuleDecl)
}
}
fn setup_module_decl(mut term: FocusedHeapRefMut) -> Result<ModuleDecl, CompilationError> {
let name = term_predicate_key(term.heap, term.focus + 1)
.map(|(name, _)| name)
.ok_or(CompilationError::InvalidModuleDecl)?;
fn setup_module_decl(mut terms: Vec<Term>) -> Result<ModuleDecl, CompilationError> {
let export_list = terms.pop().unwrap();
let name = terms.pop().unwrap();
term.focus = term.focus + 2;
let exports = setup_module_export_list(term)?;
let name = match name {
Term::Literal(_, Literal::Atom(name)) => Some(name),
_ => None,
}
.ok_or(CompilationError::InvalidModuleDecl)?;
let exports = setup_module_export_list(export_list)?;
Ok(ModuleDecl { name, exports })
}
fn setup_use_module_decl(term: &FocusedHeapRefMut) -> Result<ModuleSource, CompilationError> {
read_heap_cell!(term.deref_loc(term.focus+1),
(HeapCellValueTag::Str, s) => {
let (name, arity) = cell_as_atom_cell!(term.heap[s]).get_name_and_arity();
if (name, arity) == (atom!("library"), 1) {
read_heap_cell!(term.deref_loc(s+1),
(HeapCellValueTag::Atom, (name, arity)) => {
if arity == 0 {
return Ok(ModuleSource::Library(name));
}
}
_ => {
}
)
}
return Err(CompilationError::InvalidModuleDecl);
}
(HeapCellValueTag::Atom, (name, arity)) => {
if arity == 0 {
Ok(ModuleSource::File(name))
} else {
Err(CompilationError::InvalidUseModuleDecl)
fn setup_use_module_decl(mut terms: Vec<Term>) -> Result<ModuleSource, CompilationError> {
match terms.pop().unwrap() {
Term::Clause(_, name, mut terms) if name == atom!("library") && terms.len() == 1 => {
match terms.pop().unwrap() {
Term::Literal(_, Literal::Atom(name)) => Ok(ModuleSource::Library(name)),
_ => Err(CompilationError::InvalidModuleDecl),
}
}
_ => {
Err(CompilationError::InvalidUseModuleDecl)
}
)
Term::Literal(_, Literal::Atom(name)) => Ok(ModuleSource::File(name)),
_ => Err(CompilationError::InvalidUseModuleDecl),
}
}
type UseModuleExport = (ModuleSource, IndexSet<ModuleExport>);
fn setup_qualified_import(term: FocusedHeapRefMut) -> Result<UseModuleExport, CompilationError> {
let module_src = setup_use_module_decl(&term)?;
fn setup_qualified_import(mut terms: Vec<Term>) -> Result<UseModuleExport, CompilationError> {
let mut export_list = terms.pop().unwrap();
let module_src = match terms.pop().unwrap() {
Term::Clause(_, name, mut terms) if name == atom!("library") && terms.len() == 1 => {
match terms.pop().unwrap() {
Term::Literal(_, Literal::Atom(name)) => Ok(ModuleSource::Library(name)),
_ => Err(CompilationError::InvalidModuleDecl),
}
}
Term::Literal(_, Literal::Atom(name)) => Ok(ModuleSource::File(name)),
_ => Err(CompilationError::InvalidUseModuleDecl),
}?;
let mut exports = IndexSet::new();
let mut focus = term.focus + 2;
while let HeapCellValueTag::Lis = term.heap[focus].get_tag() {
focus = term.heap[focus].get_value() as usize;
let term = FocusedHeapRefMut {
heap: term.heap,
focus,
};
exports.insert(setup_module_export(&term)?);
focus = focus + 1;
while let Term::Cons(_, t1, t2) = export_list {
exports.insert(setup_module_export(*t1)?);
export_list = *t2;
}
if term.heap[focus] == empty_list_as_cell!() {
if let Term::Literal(_, Literal::Atom(atom!("[]"))) = export_list {
Ok((module_src, exports))
} else {
Err(CompilationError::InvalidModuleDecl)
@@ -290,20 +249,18 @@ fn setup_qualified_import(term: FocusedHeapRefMut) -> Result<UseModuleExport, Co
*/
fn setup_meta_predicate<'a, LS: LoadState<'a>>(
term: TermWriteResult,
mut terms: Vec<Term>,
loader: &mut Loader<'a, LS>,
) -> Result<(Atom, Atom, Vec<MetaSpec>), CompilationError> {
fn get_meta_specs(
term: FocusedHeapRefMut,
arity: usize,
) -> Result<Vec<MetaSpec>, CompilationError> {
fn get_name_and_meta_specs(
name: Atom,
terms: &mut [Term],
) -> Result<(Atom, Vec<MetaSpec>), CompilationError> {
let mut meta_specs = vec![];
for meta_spec_loc in term.focus + 1..term.focus + arity + 1 {
read_heap_cell!(term.deref_loc(meta_spec_loc),
(HeapCellValueTag::Atom, (meta_spec, arity)) => {
debug_assert_eq!(arity, 0);
for meta_spec in terms.iter_mut() {
match meta_spec {
Term::Literal(_, Literal::Atom(meta_spec)) => {
let meta_spec = match meta_spec {
atom!("+") => MetaSpec::Plus,
atom!("-") => MetaSpec::Minus,
@@ -314,322 +271,263 @@ fn setup_meta_predicate<'a, LS: LoadState<'a>>(
meta_specs.push(meta_spec);
}
(HeapCellValueTag::Fixnum, n) => {
match usize::try_from(n.get_num()) {
Ok(n) if n <= MAX_ARITY => {
meta_specs.push(MetaSpec::RequiresExpansionWithArgument(n));
}
_ => {
return Err(CompilationError::InvalidMetaPredicateDecl);
}
Term::Literal(_, Literal::Fixnum(n)) => match usize::try_from(n.get_num()) {
Ok(n) if n <= MAX_ARITY => {
meta_specs.push(MetaSpec::RequiresExpansionWithArgument(n));
}
}
_ => {
return Err(CompilationError::InvalidMetaPredicateDecl);
}
},
_ => {
return Err(CompilationError::InvalidMetaPredicateDecl);
}
);
}
}
Ok(meta_specs)
Ok((name, meta_specs))
}
let heap = loader.machine_heap();
let cell = heap_bound_store(heap, heap_bound_deref(heap, heap[term.focus + 1]));
match terms.pop().unwrap() {
Term::Clause(_, name, mut terms) if name == atom!(":") && terms.len() == 2 => {
let spec = terms.pop().unwrap();
let module_name = terms.pop().unwrap();
read_heap_cell!(cell,
(HeapCellValueTag::Str, s) => {
let (name, arity) = cell_as_atom_cell!(heap[s]).get_name_and_arity();
match (name, arity) {
(atom!(":"), 2) => {
let module_name = heap[s+1];
let spec = heap[s+2];
read_heap_cell!(module_name,
(HeapCellValueTag::Atom, (module_name, arity)) => {
if arity == 0 {
read_heap_cell!(spec,
(HeapCellValueTag::Str, s) => {
let (name, arity) = cell_as_atom_cell!(heap[s])
.get_name_and_arity();
let term = FocusedHeapRefMut { heap, focus: s };
return Ok((module_name, name, get_meta_specs(term, arity)?));
}
_ => {
}
);
} else {
return Err(CompilationError::InvalidMetaPredicateDecl);
}
}
_ => {
}
);
}
_ => {
let term = FocusedHeapRefMut { heap, focus: s };
let specs = get_meta_specs(term, arity)?;
let module_name = loader.payload.compilation_target.module_name();
return Ok((module_name, name, specs));
}
match module_name {
Term::Literal(_, Literal::Atom(module_name)) => match spec {
Term::Clause(_, name, mut terms) => {
let (name, meta_specs) = get_name_and_meta_specs(name, &mut terms)?;
Ok((module_name, name, meta_specs))
}
_ => Err(CompilationError::InvalidMetaPredicateDecl),
},
_ => Err(CompilationError::InvalidMetaPredicateDecl),
}
Err(CompilationError::InvalidMetaPredicateDecl)
}
_ => {
Err(CompilationError::InvalidMetaPredicateDecl)
Term::Clause(_, name, mut terms) => {
let (name, meta_specs) = get_name_and_meta_specs(name, &mut terms)?;
Ok((
loader.payload.compilation_target.module_name(),
name,
meta_specs,
))
}
)
_ => Err(CompilationError::InvalidMetaPredicateDecl),
}
}
pub(super) fn setup_declaration<'a, LS: LoadState<'a>>(
loader: &mut Loader<'a, LS>,
mut term: TermWriteResult,
mut terms: Vec<Term>,
) -> Result<Declaration, CompilationError> {
let mut focus = term.focus;
let machine_st = LS::machine_st(&mut loader.payload);
let term = terms.pop().unwrap();
loop {
let decl = machine_st.heap[focus];
read_heap_cell!(decl,
(HeapCellValueTag::Atom, (name, arity)) => {
let mut focused = FocusedHeapRefMut::from(&mut machine_st.heap, focus);
return match (name, arity) {
(atom!("dynamic"), 1) => {
let (name, arity) = setup_predicate_indicator(&focused)?;
Ok(Declaration::Dynamic(name, arity))
}
(atom!("module"), 2) => {
Ok(Declaration::Module(setup_module_decl(focused)?))
}
(atom!("op"), 3) => {
Ok(Declaration::Op(setup_op_decl(&focused)?))
}
(atom!("non_counted_backtracking"), 1) => {
focused.focus = focused.nth_arg(focused.focus, 1).unwrap();
let (name, arity) = setup_predicate_indicator(&focused)?;
Ok(Declaration::NonCountedBacktracking(name, arity))
}
(atom!("use_module"), 1) => Ok(Declaration::UseModule(setup_use_module_decl(&focused)?)),
(atom!("use_module"), 2) => {
let (name, exports) = setup_qualified_import(focused)?;
Ok(Declaration::UseQualifiedModule(name, exports))
}
(atom!("meta_predicate"), 1) => {
term.focus = focus;
let (module_name, name, meta_specs) = setup_meta_predicate(term, loader)?;
Ok(Declaration::MetaPredicate(module_name, name, meta_specs))
}
_ => Err(CompilationError::InvalidDirective(
DirectiveError::InvalidDirective(name, arity)
))
};
match term {
Term::Clause(_, name, mut terms) => match (name, terms.len()) {
(atom!("dynamic"), 1) => {
let (name, arity) = setup_predicate_indicator(&mut terms.pop().unwrap())?;
Ok(Declaration::Dynamic(name, arity))
}
(HeapCellValueTag::Str, s) => {
focus = s;
(atom!("module"), 2) => Ok(Declaration::Module(setup_module_decl(terms)?)),
(atom!("op"), 3) => Ok(Declaration::Op(setup_op_decl(terms)?)),
(atom!("non_counted_backtracking"), 1) => {
let (name, arity) = setup_predicate_indicator(&mut terms.pop().unwrap())?;
Ok(Declaration::NonCountedBacktracking(name, arity))
}
(HeapCellValueTag::AttrVar | HeapCellValueTag::Var, h) => {
if focus != h {
focus = h;
} else {
return Err(CompilationError::InvalidDirective(
DirectiveError::ExpectedDirective(decl),
));
}
(atom!("use_module"), 1) => Ok(Declaration::UseModule(setup_use_module_decl(terms)?)),
(atom!("use_module"), 2) => {
let (name, exports) = setup_qualified_import(terms)?;
Ok(Declaration::UseQualifiedModule(name, exports))
}
_ => {
return Err(CompilationError::InvalidDirective(
DirectiveError::ExpectedDirective(decl),
));
(atom!("meta_predicate"), 1) => {
let (module_name, name, meta_specs) = setup_meta_predicate(terms, loader)?;
Ok(Declaration::MetaPredicate(module_name, name, meta_specs))
}
);
_ => Err(CompilationError::InvalidDirective(
DirectiveError::InvalidDirective(name, terms.len()),
)),
},
other => Err(CompilationError::InvalidDirective(
DirectiveError::ExpectedDirective(other),
)),
}
}
fn build_meta_predicate_clause<'a, LS: LoadState<'a>>(
loader: &mut Loader<'a, LS>,
module_name: Atom,
arity: usize,
term: &TermWriteResult,
terms: Vec<Term>,
meta_specs: Vec<MetaSpec>,
) -> IndexMap<usize, CodeIndex, FxBuildHasher> {
use crate::machine::heap::Heap;
let mut index_ptrs = IndexMap::with_hasher(FxBuildHasher::default());
) -> Vec<Term> {
let mut arg_terms = Vec::with_capacity(terms.len());
let focus = {
let heap = loader.machine_heap();
let focus_cell =
heap_bound_store(heap, heap_bound_deref(heap, heap_loc_as_cell!(term.focus)));
if focus_cell.get_tag() == HeapCellValueTag::Str {
focus_cell.get_value() as usize
} else {
return index_ptrs;
}
};
for (subterm_loc, meta_spec) in (focus + 1..focus + arity + 1).zip(meta_specs) {
for (term, meta_spec) in terms.into_iter().zip(meta_specs.iter()) {
if let MetaSpec::RequiresExpansionWithArgument(supp_args) = meta_spec {
let predicate_key_opt = term_predicate_key(loader.machine_heap(), subterm_loc);
if let Some((name, arity)) = predicate_key_opt {
if let Some(name) = term.name() {
if name == atom!("$call") {
arg_terms.push(term);
continue;
}
struct QualifiedNameInfo {
module_name: Atom,
name: Atom,
arity: usize,
qualified_term_loc: usize,
}
let arity = term.arity();
fn get_qualified_name(
heap: &Heap,
module_term_loc: usize,
qualified_term_loc: usize,
) -> Option<QualifiedNameInfo> {
let (module_term_loc, _) = subterm_index(heap, module_term_loc);
let (qualified_term_loc, _) = subterm_index(heap, qualified_term_loc);
read_heap_cell!(heap[module_term_loc],
(HeapCellValueTag::Atom, (module_name, arity)) => {
if arity == 0 {
if let Some((name, arity)) = term_predicate_key(heap, qualified_term_loc) {
return Some(QualifiedNameInfo {
module_name,
name,
arity,
qualified_term_loc,
});
}
}
module_term: &Term,
qualified_term: &Term,
) -> Option<(Atom, Atom)> {
if let Term::Literal(_, Literal::Atom(module_name)) = module_term {
if let Some(name) = qualified_term.name() {
return Some((*module_name, name));
}
_ => {}
);
}
None
}
let (subterm_loc, _) = subterm_index(loader.machine_heap(), subterm_loc);
let subterm_key_opt = term_predicate_key(loader.machine_heap(), subterm_loc);
fn identity_fn(_module_name: Atom, term: Term) -> Term {
term
}
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 => {
fn tag_with_module_name(module_name: Atom, term: Term) -> Term {
Term::Clause(
Cell::default(),
atom!(":"),
vec![
Term::Literal(Cell::default(), Literal::Atom(module_name)),
term,
],
)
}
let process_term: fn(Atom, Term) -> Term;
let (module_name, key, term) = match term {
Term::Clause(cell, atom!(":"), mut terms) if terms.len() == 2 => {
if let Some((module_name, name)) = get_qualified_name(&terms[0], &terms[1])
{
process_term = tag_with_module_name;
(
module_name,
(name, terms[1].arity() + supp_args),
terms.pop().unwrap(),
)
} else {
arg_terms.push(Term::Clause(cell, atom!(":"), terms));
continue;
}
}
} else {
(module_name, (name, arity + supp_args), subterm_loc)
term => {
process_term = identity_fn;
(module_name, (name, arity + supp_args), term)
}
};
if let Some(index_ptr) = fetch_index_ptr(loader.machine_heap(), term_loc) {
index_ptrs.insert(term_loc, index_ptr);
continue;
}
let term = match term {
Term::Clause(cell, name, mut terms) => {
if let Some(Term::Literal(_, Literal::CodeIndex(_))) = terms.last() {
arg_terms
.push(process_term(module_name, Term::Clause(cell, name, terms)));
index_ptrs.insert(
term_loc,
loader.get_or_insert_qualified_code_index(module_name, key),
);
continue;
}
let idx = loader.get_or_insert_qualified_code_index(module_name, key);
terms.push(Term::Literal(Cell::default(), Literal::CodeIndex(idx)));
process_term(module_name, Term::Clause(cell, name, terms))
}
Term::Literal(cell, Literal::Atom(name)) => {
let idx = loader.get_or_insert_qualified_code_index(module_name, key);
process_term(
module_name,
Term::Clause(
cell,
name,
vec![Term::Literal(Cell::default(), Literal::CodeIndex(idx))],
),
)
}
term => term,
};
arg_terms.push(term);
continue;
}
}
arg_terms.push(term);
}
index_ptrs
arg_terms
}
#[inline]
pub(super) fn clause_to_query_term<'a, LS: LoadState<'a>>(
loader: &mut Loader<'a, LS>,
key: PredicateKey,
terms: &TermWriteResult,
term: HeapCellValue,
name: Atom,
mut terms: Vec<Term>,
call_policy: CallPolicy,
) -> QueryClause {
// supplementary code vector indices are unnecessary for
// root-level clauses.
blunt_index_ptr(loader.machine_heap(), key, terms.focus);
) -> QueryTerm {
if let Some(Term::Literal(_, Literal::CodeIndex(_))) = terms.last() {
// supplementary code vector indices are unnecessary for
// root-level clauses.
terms.pop();
}
let mut ct = loader.get_clause_type(key.0, key.1);
let mut ct = loader.get_clause_type(name, terms.len());
if let ClauseType::Named(arity, name, idx) = ct {
if let Some(meta_specs) = loader.get_meta_specs(name, arity).cloned() {
let module_name = loader.payload.compilation_target.module_name();
let code_indices =
build_meta_predicate_clause(loader, module_name, arity, terms, meta_specs);
let terms = build_meta_predicate_clause(loader, module_name, terms, meta_specs);
return QueryClause {
ct: ClauseType::Named(key.1, key.0, idx),
term,
code_indices,
return QueryTerm::Clause(
Cell::default(),
ClauseType::Named(arity, name, idx),
terms,
call_policy,
};
);
}
ct = ClauseType::Named(key.1, key.0, idx);
ct = ClauseType::Named(arity, name, idx);
}
QueryClause {
ct,
term,
code_indices: IndexMap::with_hasher(FxBuildHasher::default()),
call_policy,
}
QueryTerm::Clause(Cell::default(), ct, terms, call_policy)
}
#[inline]
pub(super) fn qualified_clause_to_query_term<'a, LS: LoadState<'a>>(
loader: &mut Loader<'a, LS>,
key: PredicateKey,
module_name: Atom,
terms: &TermWriteResult,
term: HeapCellValue,
name: Atom,
mut terms: Vec<Term>,
call_policy: CallPolicy,
) -> QueryClause {
// supplementary code vector indices are unnecessary for
// root-level clauses.
blunt_index_ptr(loader.machine_heap(), key, terms.focus);
) -> QueryTerm {
if let Some(Term::Literal(_, Literal::CodeIndex(_))) = terms.last() {
// supplementary code vector indices are unnecessary for
// root-level clauses.
terms.pop();
}
let mut ct = loader.get_qualified_clause_type(module_name, key.0, key.1);
let mut ct = loader.get_qualified_clause_type(module_name, name, terms.len());
if let ClauseType::Named(arity, name, idx) = ct {
if let Some(meta_specs) = loader.get_meta_specs(name, arity).cloned() {
let code_indices =
build_meta_predicate_clause(loader, module_name, arity, &terms, meta_specs);
let terms = build_meta_predicate_clause(loader, module_name, terms, meta_specs);
return QueryClause {
ct: ClauseType::Named(key.1, key.0, idx),
term,
code_indices,
return QueryTerm::Clause(
Cell::default(),
ClauseType::Named(arity, name, idx),
terms,
call_policy,
};
);
}
ct = ClauseType::Named(key.1, key.0, idx);
ct = ClauseType::Named(arity, name, idx);
}
QueryClause {
ct,
term,
code_indices: IndexMap::with_hasher(FxBuildHasher::default()),
call_policy,
}
QueryTerm::Clause(Cell::default(), ct, terms, call_policy)
}
#[derive(Debug)]
@@ -642,66 +540,70 @@ impl Preprocessor {
Preprocessor { settings }
}
pub fn setup_fact<'a, LS: LoadState<'a>>(
&mut self,
loader: &mut Loader<'a, LS>,
term: TermWriteResult,
) -> Result<(Fact, VarData), CompilationError> {
let heap = loader.machine_heap();
fn setup_fact(&mut self, term: Term) -> Result<(Fact, VarData), CompilationError> {
match term {
Term::Clause(..) | Term::Literal(_, Literal::Atom(..)) => {
let classifier = VariableClassifier::new(self.settings.default_call_policy());
if term_predicate_key(heap, term.focus).is_some() {
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,
))
} else {
Err(CompilationError::InadmissibleFact)
let (head, var_data) = classifier.classify_fact(term)?;
Ok((Fact { head }, var_data))
}
_ => Err(CompilationError::InadmissibleFact),
}
}
fn setup_rule<'a, LS: LoadState<'a>>(
&mut self,
loader: &mut Loader<'a, LS>,
term: TermWriteResult,
head: Term,
body: Term,
) -> Result<(Rule, VarData), CompilationError> {
let classifier = VariableClassifier::new(self.settings.default_call_policy());
let (clauses, var_data) = classifier.classify_rule(loader, &term)?;
let heap = loader.machine_heap();
let head_loc = term_nth_arg(heap, term.focus, 1).unwrap();
let (head, clauses, var_data) = classifier.classify_rule(loader, head, body)?;
if term_predicate_key(heap, head_loc).is_some() {
Ok((
match head {
Term::Clause(_, name, terms) => Ok((
Rule {
term_loc: term.focus,
head: (name, terms),
clauses,
},
var_data,
))
} else {
Err(CompilationError::InvalidRuleHead)
)),
Term::Literal(_, Literal::Atom(name)) => Ok((
Rule {
head: (name, vec![]),
clauses,
},
var_data,
)),
_ => Err(CompilationError::InvalidRuleHead),
}
}
pub(super) fn try_term_to_tl<'a, LS: LoadState<'a>>(
&mut self,
loader: &mut Loader<'a, LS>,
term: TermWriteResult,
term: Term,
) -> Result<PredicateClause, CompilationError> {
let heap = &LS::machine_st(&mut loader.payload).heap;
match term {
Term::Clause(r, name, mut terms) => {
let is_rule = name == atom!(":-") && terms.len() == 2;
match term_predicate_key(heap, term.focus) {
Some((atom!(":-"), 2)) => {
let (rule, var_data) = self.setup_rule(loader, term)?;
Ok(PredicateClause::Rule(rule, var_data))
if is_rule {
let tail = terms.pop().unwrap();
let head = terms.pop().unwrap();
let (rule, var_data) = self.setup_rule(loader, head, tail)?;
Ok(PredicateClause::Rule(rule, var_data))
} else {
let term = Term::Clause(r, name, terms);
let (fact, var_data) = self.setup_fact(term)?;
Ok(PredicateClause::Fact(fact, var_data))
}
}
_ => {
let (fact, var_data) = self.setup_fact(loader, term)?;
term => {
let (fact, var_data) = self.setup_fact(term)?;
Ok(PredicateClause::Fact(fact, var_data))
}
}

View File

@@ -24,7 +24,12 @@ pub(crate) struct RawBlock<T: RawBlockTraits> {
impl<T: RawBlockTraits> RawBlock<T> {
pub(crate) fn new() -> Self {
let mut block = Self::uninitialized();
let mut block = RawBlock {
size: 0,
base: ptr::null(),
top: ptr::null(),
_marker: PhantomData,
};
unsafe {
block.grow();
@@ -33,15 +38,6 @@ impl<T: RawBlockTraits> RawBlock<T> {
block
}
pub(crate) fn uninitialized() -> Self {
Self {
size: 0,
base: ptr::null(),
top: ptr::null(),
_marker: PhantomData,
}
}
unsafe fn init_at_size(&mut self, cap: usize) {
let layout = alloc::Layout::from_size_align_unchecked(cap, T::align());

View File

@@ -168,13 +168,6 @@ impl Stack {
}
}
pub(crate) fn uninitialized() -> Self {
Stack {
buf: RawBlock::empty_block(),
_marker: PhantomData,
}
}
#[inline(always)]
unsafe fn alloc(&mut self, frame_size: usize) -> *mut u8 {
loop {

View File

@@ -1808,59 +1808,60 @@ impl MachineState {
let addr = self.store(MachineState::deref(self, addr));
read_heap_cell!(addr,
(HeapCellValueTag::Atom, (name, arity)) => {
debug_assert_eq!(arity, 0);
(HeapCellValueTag::Atom, (name, arity)) => {
debug_assert_eq!(arity, 0);
return match indices.get_stream(name) {
Some(stream) => Ok(stream),
_ => {
let stub = functor_stub(caller, arity);
let addr = atom_as_cell!(name);
return match indices.get_stream(name) {
Some(stream) => Ok(stream),
_ => {
let stub = functor_stub(caller, arity);
let addr = atom_as_cell!(name);
let existence_error = self.existence_error(ExistenceError::Stream(addr));
let existence_error = self.existence_error(ExistenceError::Stream(addr));
Err(self.error_form(existence_error, stub))
}
};
}
(HeapCellValueTag::Str, s) => {
let (name, arity) = cell_as_atom_cell!(self.heap[s])
.get_name_and_arity();
Err(self.error_form(existence_error, stub))
}
};
}
(HeapCellValueTag::Str, s) => {
let (name, arity) = cell_as_atom_cell!(self.heap[s])
.get_name_and_arity();
debug_assert_eq!(arity, 0);
debug_assert_eq!(arity, 0);
return match indices.get_stream(name) {
Some(stream) => Ok(stream),
_ => {
let stub = functor_stub(caller, arity);
let addr = atom_as_cell!(name);
return match indices.get_stream(name) {
Some(stream) => Ok(stream),
_ => {
let stub = functor_stub(caller, arity);
let addr = atom_as_cell!(name);
let existence_error = self.existence_error(ExistenceError::Stream(addr));
let existence_error = self.existence_error(ExistenceError::Stream(addr));
Err(self.error_form(existence_error, stub))
}
};
}
(HeapCellValueTag::Cons, ptr) => {
match_untyped_arena_ptr!(ptr,
(ArenaHeaderTag::Stream, stream) => {
if stream.is_null_stream() {
unreachable!("Null streams have no Cons representation");
}
return Ok(stream);
}
(ArenaHeaderTag::Dropped, _value) => {
let stub = functor_stub(caller, arity);
let err = self.existence_error(ExistenceError::Stream(addr));
Err(self.error_form(existence_error, stub))
}
};
}
(HeapCellValueTag::Cons, ptr) => {
match_untyped_arena_ptr!(ptr,
(ArenaHeaderTag::Stream, stream) => {
return if stream.is_null_stream() {
Err(self.open_permission_error(stream_as_cell!(stream), caller, arity))
} else {
Ok(stream)
};
}
(ArenaHeaderTag::Dropped, _value) => {
let stub = functor_stub(caller, arity);
let err = self.existence_error(ExistenceError::Stream(addr));
return Err(self.error_form(err, stub));
}
_ => {
}
);
}
_ => {
}
return Err(self.error_form(err, stub));
}
_ => {
}
);
}
_ => {
}
);
let stub = functor_stub(caller, arity);
@@ -1880,7 +1881,7 @@ impl MachineState {
) -> Result<Stream, ParserError> {
match stream.peek_char() {
None => Ok(stream), // empty stream is handled gracefully by Lexer::eof
Some(Err(e)) => Err(ParserError::IO(e, ParserErrorSrc::default())),
Some(Err(e)) => Err(ParserError::IO(e)),
Some(Ok(c)) => {
if c == '\u{feff}' {
// skip UTF-8 BOM
@@ -2086,7 +2087,7 @@ impl MachineState {
_ => {
// assume the OS is out of file descriptors.
let stub = functor_stub(atom!("open"), 4);
let err = self.resource_error(ResourceError::OutOfFiles);
let err = Self::resource_error(ResourceError::OutOfFiles);
return Err(self.error_form(err, stub));
}

View File

@@ -1,7 +1,3 @@
use crate::parser::ast::*;
use crate::parser::lexer::LexerParser;
use crate::parser::parser::*;
use base64::Engine;
use dashu::integer::{Sign, UBig};
use lazy_static::lazy_static;
@@ -29,8 +25,10 @@ use crate::machine::partial_string::*;
use crate::machine::stack::*;
use crate::machine::streams::*;
use crate::machine::{get_structure_index, Machine, VERIFY_ATTR_INTERRUPT_LOC};
use crate::parser::ast::*;
use crate::parser::char_reader::*;
use crate::parser::dashu::{Integer, Rational};
use crate::parser::dashu::Integer;
use crate::parser::parser::*;
use crate::read::*;
use crate::types::*;
use rand::rngs::StdRng;
@@ -41,6 +39,7 @@ use ordered_float::OrderedFloat;
use fxhash::{FxBuildHasher, FxHasher};
use indexmap::IndexSet;
use std::cell::Cell;
use std::cmp::Ordering;
use std::convert::TryFrom;
use std::env;
@@ -851,12 +850,10 @@ impl MachineState {
) {
let mut seen_set = IndexSet::new();
if term.is_ref() {
let mut iter = stackful_post_order_iter::<NonListElider>(
&mut self.heap,
&mut self.stack,
term.get_value() as usize,
);
{
self.heap[0] = term;
let mut iter =
stackful_post_order_iter::<NonListElider>(&mut self.heap, &mut self.stack, 0);
while let Some(value) = iter.next() {
if iter.parent_stack_len() >= max_depth {
@@ -874,9 +871,8 @@ impl MachineState {
let outcome = step_or_resource_error!(
self,
sized_iter_to_heap_list(&mut self.heap, seen_set.len(), seen_set.into_iter(),)
sized_iter_to_heap_list(&mut self.heap, seen_set.len(), seen_set.into_iter())
);
unify_fn!(*self, list_of_vars, outcome);
}
@@ -959,7 +955,7 @@ impl MachineState {
let nx = self.store(self.deref(self.registers[2]));
let iter = std::io::Cursor::new(string);
let mut lexer_parser = LexerParser::new(CharReader::new(iter), self);
let mut lexer = Lexer::new(CharReader::new(iter), self);
let mut tokens = vec![];
match lexer.next_number_token() {
@@ -980,58 +976,35 @@ impl MachineState {
}
loop {
match lexer_parser.lookahead_char() {
match lexer.lookahead_char() {
Err(e) if e.is_unexpected_eof() => {
let mut parser = Parser::from_lexer(lexer);
let op_dir = CompositeOpDir::new(&indices.op_dir, None);
tokens.reverse();
let byte_size = heap_index!(tokens.len());
match lexer_parser.read_term(&op_dir, Tokens::Provided(tokens, byte_size)) {
Ok(term) => {
read_heap_cell!(lexer_parser.machine_st.heap[term.focus],
(HeapCellValueTag::Cons, c) => {
match_untyped_arena_ptr!(c,
(ArenaHeaderTag::Rational, n) => {
self.unify_rational(n, nx);
}
(ArenaHeaderTag::Integer, n) => {
self.unify_big_int(n, nx);
}
_ => {
let e = ParserError::ParseBigInt(lexer_parser.loc_to_err_src());
let e = self.syntax_error(e);
return Err(self.error_form(e, stub_gen()));
}
)
}
(HeapCellValueTag::F64, n) => {
self.unify_f64(n, nx);
}
(HeapCellValueTag::Fixnum, n) => {
self.unify_fixnum(n, nx);
}
_ => {
let e = ParserError::ParseBigInt(lexer_parser.loc_to_err_src());
let e = self.syntax_error(e);
return Err(self.error_form(e, stub_gen()));
}
);
return Ok(());
match parser.read_term(&op_dir, Tokens::Provided(tokens)) {
Err(err) => {
let err = self.syntax_error(err);
return Err(self.error_form(err, stub_gen()));
}
Err(e) => {
let e = self.syntax_error(e);
return Err(self.error_form(e, stub_gen()));
Ok(Term::Literal(_, cell)) => {
unify!(self, nx, HeapCellValue::from(cell));
}
_ => {
let err = ParserError::ParseBigInt(0, 0);
let err = self.syntax_error(err);
return Err(self.error_form(err, stub_gen()));
}
}
return Ok(());
}
Ok(c) => {
let err_src = lexer_parser.loc_to_err_src();
let (line_num, col_num) = (lexer.line_num, lexer.col_num);
let err = ParserError::UnexpectedChar(c, err_src);
let err = ParserError::UnexpectedChar(c, line_num, col_num);
let err = self.syntax_error(err);
return Err(self.error_form(err, stub_gen()));
@@ -1645,12 +1618,12 @@ impl Machine {
let vars: Vec<_> = vars
.union(&result.supp_vars) // difference + union does not cancel.
.cloned()
.map(|v| Term::Var(Cell::default(), VarPtr::from(format!("_{}", v.get_value()))))
.collect();
let helper_clause_loc = self.code.len();
match self.compile_standalone_clause(temp_v!(1), vars) {
match self.compile_standalone_clause(temp_v!(1), &vars) {
Err(e) => {
let err = self.machine_st.session_error(e);
let stub = functor_stub(atom!("call"), result.key.1);
@@ -1996,7 +1969,7 @@ impl Machine {
if let Some(name) = entry.file_name().to_str() {
let file_string_cell = resource_error_call_result!(
self.machine_st,
self.machine_st.allocate_cstr(name)
self.machine_st.heap.allocate_cstr(name)
);
files.push(file_string_cell);
@@ -2115,7 +2088,7 @@ impl Machine {
let cstr_cell = step_or_resource_error!(
self.machine_st,
self.machine_st.allocate_cstr(&chars_string)
self.machine_st.heap.allocate_cstr(&chars_string)
);
unify!(self.machine_st, cstr_cell, self.machine_st.registers[3]);
@@ -2251,7 +2224,7 @@ impl Machine {
let current_string = resource_error_call_result!(
self.machine_st,
self.machine_st.allocate_cstr(current)
self.machine_st.heap.allocate_cstr(current)
);
unify!(
@@ -2295,8 +2268,10 @@ impl Machine {
}
};
let canonical_string =
resource_error_call_result!(self.machine_st, self.machine_st.allocate_cstr(cs));
let canonical_string = resource_error_call_result!(
self.machine_st,
self.machine_st.heap.allocate_cstr(cs)
);
unify!(
self.machine_st,
@@ -2321,7 +2296,7 @@ impl Machine {
let cell = step_or_resource_error!(
self.machine_st,
self.machine_st.allocate_cstr(&*name.as_str())
self.machine_st.heap.allocate_cstr(&*name.as_str())
);
unify!(self.machine_st, self.machine_st.registers[2], cell);
@@ -2522,7 +2497,7 @@ impl Machine {
let pstr_loc_cell = step_or_resource_error!(
self.machine_st,
self.machine_st.allocate_pstr(&*atom.as_str())
self.machine_st.heap.allocate_pstr(&*atom.as_str())
);
let tail_loc = Heap::pstr_tail_idx(atom.as_str().len() + heap_index!(pstr_h));
@@ -2897,7 +2872,7 @@ impl Machine {
let cstr_cell = step_or_resource_error!(
self.machine_st,
self.machine_st.allocate_cstr(string.trim())
self.machine_st.heap.allocate_cstr(string.trim())
);
unify!(self.machine_st, cstr_cell, chs);
@@ -3137,7 +3112,7 @@ impl Machine {
let reg = self.machine_st.deref(self.machine_st.heap[s+1]);
let upper_str = step_or_resource_error!(
self.machine_st,
self.machine_st.allocate_cstr(&c.to_uppercase().to_string())
self.machine_st.heap.allocate_cstr(&c.to_uppercase().to_string())
);
unify!(self.machine_st, reg, upper_str);
}
@@ -3145,7 +3120,7 @@ impl Machine {
let reg = self.machine_st.deref(self.machine_st.heap[s+1]);
let lower_str = step_or_resource_error!(
self.machine_st,
self.machine_st.allocate_cstr(&c.to_uppercase().to_string())
self.machine_st.heap.allocate_cstr(&c.to_uppercase().to_string())
);
unify!(self.machine_st, reg, lower_str);
@@ -3660,12 +3635,7 @@ impl Machine {
}
Some(Err(e)) => {
let stub = functor_stub(atom!("$get_n_chars"), 3);
let err =
self.machine_st
.session_error(SessionError::from(ParserError::IO(
e,
ParserErrorSrc::default(),
)));
let err = self.machine_st.session_error(SessionError::from(e));
return Err(self.machine_st.error_form(err, stub));
}
@@ -3677,8 +3647,10 @@ impl Machine {
};
let output = self.deref_register(3);
let cstr_cell =
resource_error_call_result!(self.machine_st, self.machine_st.allocate_cstr(&string));
let cstr_cell = resource_error_call_result!(
self.machine_st,
self.machine_st.heap.allocate_cstr(&string)
);
unify!(self.machine_st, cstr_cell, output);
Ok(())
@@ -4403,9 +4375,7 @@ impl Machine {
Ok(Number::Integer(n)) => match (&*n).try_into() as Result<usize, _> {
Ok(n) => n,
Err(_) => {
let err = self
.machine_st
.resource_error(ResourceError::FiniteMemory(len));
let err = MachineState::resource_error(ResourceError::FiniteMemory(len));
return Err(self.machine_st.error_form(err, stub_gen()));
}
},
@@ -4508,6 +4478,7 @@ impl Machine {
let string_cell = resource_error_call_result!(
self.machine_st,
self.machine_st
.heap
.allocate_cstr(header_value.to_str().unwrap())
);
@@ -4568,7 +4539,7 @@ impl Machine {
}
}
Ok(())
Ok::<(), _>(())
})?;
} else {
let err = self
@@ -4758,7 +4729,7 @@ impl Machine {
let path_atom = AtomTable::build_with(&self.machine_st.atom_tbl, &request.request_data.path);
let path_cell = resource_error_call_result!(
self.machine_st,
self.machine_st.allocate_cstr(&request.request_data.path)
self.machine_st.heap.allocate_cstr(&request.request_data.path)
);
let mut headers = vec![];
@@ -4766,7 +4737,7 @@ impl Machine {
for (header_name, header_value) in request.request_data.headers {
let header_value = resource_error_call_result!(
self.machine_st,
self.machine_st.allocate_cstr(header_value.to_str().unwrap())
self.machine_st.heap.allocate_cstr(header_value.to_str().unwrap())
);
let header_term = functor!(
@@ -4796,7 +4767,7 @@ impl Machine {
let query_str = request.request_data.query;
let query_cell = resource_error_call_result!(
self.machine_st,
self.machine_st.allocate_cstr(&query_str)
self.machine_st.heap.allocate_cstr(&query_str)
);
let mut stream = Stream::from_http_stream(
@@ -5064,7 +5035,7 @@ impl Machine {
Value::CString(cstr) => {
let str_cell = resource_error_call_result!(
self.machine_st,
self.machine_st.allocate_cstr(cstr.to_str().unwrap())
self.machine_st.heap.allocate_cstr(cstr.to_str().unwrap())
);
unify!(self.machine_st, str_cell, return_value);
@@ -5208,8 +5179,10 @@ impl Machine {
let mut args_pstrs = vec![];
for arg in env::args() {
let pstr_cell =
resource_error_call_result!(self.machine_st, self.machine_st.allocate_cstr(&arg));
let pstr_cell = resource_error_call_result!(
self.machine_st,
self.machine_st.heap.allocate_cstr(&arg)
);
args_pstrs.push(pstr_cell);
}
@@ -5230,8 +5203,10 @@ impl Machine {
#[inline(always)]
pub(crate) fn current_time(&mut self) {
let timestamp = self.systemtime_to_timestamp(SystemTime::now());
let cstr_cell =
step_or_resource_error!(self.machine_st, self.machine_st.allocate_cstr(&timestamp));
let cstr_cell = step_or_resource_error!(
self.machine_st,
self.machine_st.heap.allocate_cstr(&timestamp)
);
unify!(self.machine_st, cstr_cell, self.machine_st.registers[1]);
}
@@ -6494,7 +6469,7 @@ impl Machine {
}
#[inline(always)]
fn read_term_from_atom(
fn read_term_and_write_to_heap(
&mut self,
atom_or_string: AtomOrString,
) -> Result<Option<TermWriteResult>, MachineStub> {
@@ -6504,15 +6479,16 @@ impl Machine {
};
let chars = CharReader::new(ByteStream::from_string(string));
let mut parser = LexerParser::new(chars, &mut self.machine_st);
let mut parser = Parser::new(chars, &mut self.machine_st);
let op_dir = CompositeOpDir::new(&self.indices.op_dir, None);
let term = parser
let term_write_result = parser
.read_term(&op_dir, Tokens::Default)
.map_err(|e| error_after_read_term(e, 0));
.map_err(|err| error_after_read_term(err, 0, &parser))
.and_then(|term| write_term_to_heap(&term, &mut self.machine_st.heap));
match term {
Ok(term) => Ok(Some(term)),
match term_write_result {
Ok(term_write_result) => Ok(Some(term_write_result)),
Err(CompilationError::ParserError(e)) if e.is_unexpected_eof() => {
let value = self.machine_st.registers[2];
self.machine_st.unify_atom(atom!("end_of_file"), value);
@@ -6530,46 +6506,43 @@ impl Machine {
#[inline(always)]
pub(crate) fn read_from_chars(&mut self) -> CallResult {
let atom_or_string = self
if let Some(atom_or_string) = self
.machine_st
.value_to_str_like(self.machine_st.registers[1])
.unwrap();
{
if let Some(term_write_result) = self.read_term_and_write_to_heap(atom_or_string)? {
let result = heap_loc_as_cell!(term_write_result.heap_loc);
let var = self.deref_register(2).as_var().unwrap();
if let Some(term) = self.read_term_from_atom(atom_or_string)? {
let result = self.machine_st.heap[term.focus];
let var = self.deref_register(2).as_var().unwrap();
self.machine_st.bind(var, result);
}
self.machine_st.bind(var, result);
Ok(())
} else {
unreachable!()
}
Ok(())
}
#[inline(always)]
pub(crate) fn read_term_from_chars(&mut self) -> CallResult {
let atom_or_string = self
if let Some(atom_or_string) = self
.machine_st
.value_to_str_like(self.machine_st.registers[1])
.unwrap();
{
if let Some(term_write_result) = self.read_term_and_write_to_heap(atom_or_string)? {
self.machine_st.read_term_body(term_write_result)
} else {
if !self.machine_st.fail {
// wrote end_of_file term in this case.
self.machine_st
.write_read_term_options(vec![], empty_list_as_cell!())?;
}
let string = match atom_or_string {
AtomOrString::Atom(atom!("[]")) => "".to_owned(),
_ => atom_or_string.into(),
};
let chars = CharReader::new(ByteStream::from_string(string));
let term = self
.machine_st
.read(chars, &self.indices.op_dir)
.map(|(term, _)| term)
.map_err(|e| {
let e = self.machine_st.session_error(SessionError::from(e));
let stub = functor_stub(atom!("read_term_from_chars"), 3);
self.machine_st.error_form(e, stub)
})?;
self.machine_st.read_term_body(term)
Ok(())
}
} else {
unreachable!()
}
}
#[inline(always)]
@@ -7542,8 +7515,10 @@ impl Machine {
};
let result = printer.print().result();
let chars =
resource_error_call_result!(self.machine_st, self.machine_st.allocate_cstr(&result));
let chars = resource_error_call_result!(
self.machine_st,
self.machine_st.heap.allocate_cstr(&result)
);
let result_addr = self.deref_register(1);
let var = result_addr.as_var().unwrap();
@@ -7559,7 +7534,7 @@ impl Machine {
let buffer = git_version!(cargo_prefix = "cargo:", fallback = "unknown");
let cstr_cell =
step_or_resource_error!(self.machine_st, self.machine_st.allocate_cstr(&buffer));
step_or_resource_error!(self.machine_st, self.machine_st.heap.allocate_cstr(&buffer));
unify!(self.machine_st, cstr_cell, self.machine_st.registers[1]);
}
@@ -8010,7 +7985,10 @@ impl Machine {
if buffer.is_empty() {
empty_list_as_cell!()
} else {
step_or_resource_error!(self.machine_st, self.machine_st.allocate_cstr(&buffer))
step_or_resource_error!(
self.machine_st,
self.machine_st.heap.allocate_cstr(&buffer)
)
}
};
@@ -8197,7 +8175,7 @@ impl Machine {
Ok(value) => {
let cstr = step_or_resource_error!(
self.machine_st,
self.machine_st.allocate_cstr(&value)
self.machine_st.heap.allocate_cstr(&value)
);
unify!(self.machine_st, self.machine_st.registers[2], cstr);
@@ -8410,20 +8388,15 @@ impl Machine {
1,
)?;
let mut lexer_parser = LexerParser::new(stream, &mut self.machine_st);
let mut parser = Parser::new(stream, &mut self.machine_st);
match devour_whitespace(&mut lexer_parser) {
match devour_whitespace(&mut parser.lexer) {
Ok(false) => {
// not at EOF ...
stream.add_lines_read(lexer_parser.line_num());
// ... unless we are.
if stream.at_end_of_stream() {
self.machine_st.fail = true;
}
// not at EOF.
stream.add_lines_read(parser.lines_read());
}
Ok(true) => {
stream.add_lines_read(lexer_parser.line_num());
stream.add_lines_read(parser.lexer.line_num);
self.machine_st.fail = true;
}
Err(err) => {
@@ -8483,8 +8456,10 @@ impl Machine {
if path.is_dir() {
if let Some(path) = path.to_str() {
let path_string =
step_or_resource_error!(self.machine_st, self.machine_st.allocate_cstr(path));
let path_string = step_or_resource_error!(
self.machine_st,
self.machine_st.heap.allocate_cstr(path)
);
unify!(self.machine_st, self.machine_st.registers[1], path_string);
return;
@@ -8557,13 +8532,13 @@ impl Machine {
node: roxmltree::Node,
) -> Result<HeapCellValue, usize> {
if node.is_text() {
self.machine_st.allocate_cstr(node.text().unwrap())
self.machine_st.heap.allocate_cstr(node.text().unwrap())
} else {
let mut avec = Vec::new();
for attr in node.attributes() {
let name = AtomTable::build_with(&self.machine_st.atom_tbl, attr.name());
let value = self.machine_st.allocate_cstr(attr.value())?;
let value = self.machine_st.heap.allocate_cstr(attr.value())?;
avec.push(str_loc_as_cell!(self.machine_st.heap.cell_len()));
@@ -8610,13 +8585,14 @@ impl Machine {
match node.value().as_element() {
None => self
.machine_st
.heap
.allocate_cstr(&node.value().as_text().unwrap().text),
Some(element) => {
let mut avec = Vec::new();
for attr in element.attrs() {
let name = AtomTable::build_with(&self.machine_st.atom_tbl, attr.0);
let value = self.machine_st.allocate_cstr(attr.1)?;
let value = self.machine_st.heap.allocate_cstr(attr.1)?;
avec.push(str_loc_as_cell!(self.machine_st.heap.cell_len()));
@@ -8669,7 +8645,7 @@ impl Machine {
if buffer.is_empty() {
Ok(empty_list_as_cell!())
} else {
self.machine_st.allocate_cstr(&buffer)
self.machine_st.heap.allocate_cstr(&buffer)
}
}
}

View File

@@ -21,11 +21,11 @@ pub struct LoadStatePayload<TS> {
pub(super) module_op_exports: ModuleOpExports,
pub(super) non_counted_bt_preds: IndexSet<PredicateKey, FxBuildHasher>,
pub(super) predicates: PredicateQueue,
pub(super) clause_clauses: Vec<TermWriteResult>,
pub(super) clause_clauses: Vec<(Term, Term)>,
}
pub trait TermStream: Sized {
fn next(&mut self, op_dir: &CompositeOpDir) -> Result<TermWriteResult, CompilationError>;
fn next(&mut self, op_dir: &CompositeOpDir) -> Result<Term, CompilationError>;
fn eof(&mut self) -> Result<bool, CompilationError>;
fn listing_src(&self) -> &ListingSource;
}
@@ -33,7 +33,7 @@ pub trait TermStream: Sized {
#[derive(Debug)]
pub struct BootstrappingTermStream<'a> {
listing_src: ListingSource,
pub(super) lexer_parser: LexerParser<'a, Stream>,
pub(super) parser: Parser<'a, Stream>,
}
impl<'a> BootstrappingTermStream<'a> {
@@ -43,9 +43,9 @@ impl<'a> BootstrappingTermStream<'a> {
machine_st: &'a mut MachineState,
listing_src: ListingSource,
) -> Self {
let lexer_parser = LexerParser::new(stream, machine_st);
let parser = Parser::new(stream, machine_st);
Self {
lexer_parser,
parser,
listing_src,
}
}
@@ -53,18 +53,16 @@ impl<'a> BootstrappingTermStream<'a> {
impl<'a> TermStream for BootstrappingTermStream<'a> {
#[inline]
fn next(&mut self, op_dir: &CompositeOpDir) -> Result<TermWriteResult, CompilationError> {
let result = self
.lexer_parser
fn next(&mut self, op_dir: &CompositeOpDir) -> Result<Term, CompilationError> {
self.parser.reset();
self.parser
.read_term(op_dir, Tokens::Default)
.map_err(CompilationError::from);
result
.map_err(CompilationError::from)
}
#[inline]
fn eof(&mut self) -> Result<bool, CompilationError> {
devour_whitespace(&mut self.lexer_parser) // eliminate dangling comments before checking for EOF.
devour_whitespace(&mut self.parser.lexer) // eliminate dangling comments before checking for EOF.
.map_err(CompilationError::from)
}
@@ -75,7 +73,7 @@ impl<'a> TermStream for BootstrappingTermStream<'a> {
}
pub struct LiveTermStream {
pub(super) term_queue: VecDeque<TermWriteResult>,
pub(super) term_queue: VecDeque<Term>,
pub(super) listing_src: ListingSource,
}
@@ -111,7 +109,7 @@ impl<TS> LoadStatePayload<TS> {
impl TermStream for LiveTermStream {
#[inline]
fn next(&mut self, _: &CompositeOpDir) -> Result<TermWriteResult, CompilationError> {
fn next(&mut self, _: &CompositeOpDir) -> Result<Term, CompilationError> {
Ok(self.term_queue.pop_front().unwrap())
}
@@ -129,10 +127,8 @@ impl TermStream for LiveTermStream {
pub struct InlineTermStream {}
impl TermStream for InlineTermStream {
fn next(&mut self, _: &CompositeOpDir) -> Result<TermWriteResult, CompilationError> {
Err(CompilationError::from(ParserError::unexpected_eof(
ParserErrorSrc::default(),
)))
fn next(&mut self, _: &CompositeOpDir) -> Result<Term, CompilationError> {
Err(CompilationError::from(ParserError::unexpected_eof()))
}
fn eof(&mut self) -> Result<bool, CompilationError> {

View File

@@ -133,11 +133,14 @@ pub(crate) trait Unifier: DerefMut<Target = MachineState> {
machine_st.partial_string_to_pdl(pstr_loc, l);
}
(HeapCellValueTag::PStrLoc, other_pstr_loc) => {
let cmp_result = machine_st.heap.compare_pstr_segments(pstr_loc, other_pstr_loc);
if cmp_result.continue_pstr_compare(&mut machine_st.pdl).is_some() {
debug_assert!(matches!(cmp_result, PStrSegmentCmpResult::Mismatch { .. }));
machine_st.fail = true;
match machine_st.heap.compare_pstr_segments(pstr_loc, other_pstr_loc) {
PStrSegmentCmpResult::Continue(v1, v2) => {
machine_st.pdl.push(v1);
machine_st.pdl.push(v2);
}
_ => {
machine_st.fail = true;
}
}
}
_ => {
@@ -501,10 +504,8 @@ fn bind_with_occurs_check<U: Unifier>(unifier: &mut U, r: Ref, value: HeapCellVa
let mut occurs_triggered = false;
let machine_st: &mut MachineState = unifier.deref_mut();
let value = machine_st.store(MachineState::deref(machine_st, value));
if value.is_ref() && !value.is_stack_var() {
if !value.is_constant() {
let machine_st: &mut MachineState = unifier.deref_mut();
machine_st.heap[0] = value;
for cell in