remove Term
This commit is contained in:
272
src/read.rs
272
src/read.rs
@@ -2,19 +2,12 @@ use crate::parser::ast::*;
|
||||
use crate::parser::parser::*;
|
||||
|
||||
use crate::atom_table::*;
|
||||
use crate::forms::*;
|
||||
use crate::iterators::*;
|
||||
use crate::machine::heap::*;
|
||||
use crate::machine::machine_errors::*;
|
||||
use crate::machine::machine_indices::*;
|
||||
use crate::machine::machine_state::MachineState;
|
||||
use crate::machine::machine_state::{MachineState, copy_and_align_iter};
|
||||
use crate::machine::streams::*;
|
||||
use crate::parser::char_reader::*;
|
||||
#[cfg(feature = "repl")]
|
||||
use crate::repl_helper::Helper;
|
||||
use crate::types::*;
|
||||
|
||||
use fxhash::FxBuildHasher;
|
||||
|
||||
#[cfg(feature = "repl")]
|
||||
use rustyline::error::ReadlineError;
|
||||
@@ -23,14 +16,11 @@ use rustyline::history::DefaultHistory;
|
||||
#[cfg(feature = "repl")]
|
||||
use rustyline::{Config, Editor};
|
||||
|
||||
use std::collections::VecDeque;
|
||||
use std::io::{Cursor, Read};
|
||||
#[cfg(feature = "repl")]
|
||||
use std::io::{Error, ErrorKind};
|
||||
use std::sync::Arc;
|
||||
|
||||
type SubtermDeque = VecDeque<(usize, usize)>;
|
||||
|
||||
pub(crate) fn devour_whitespace<R: CharRead>(
|
||||
parser: &mut Parser<'_, R>,
|
||||
) -> Result<bool, ParserError> {
|
||||
@@ -41,46 +31,72 @@ pub(crate) fn devour_whitespace<R: CharRead>(
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn error_after_read_term<R>(
|
||||
pub(crate) fn error_after_read_term(
|
||||
err: ParserError,
|
||||
prior_num_lines_read: usize,
|
||||
parser: &Parser<R>,
|
||||
) -> CompilationError {
|
||||
if err.is_unexpected_eof() {
|
||||
let line_num = parser.lexer.line_num;
|
||||
let col_num = parser.lexer.col_num;
|
||||
let ParserErrorSrc { line_num, col_num } = err.err_src();
|
||||
|
||||
// rough overlap with errors 8.14.1.3 k) & l) of the ISO standard here
|
||||
if !(line_num == prior_num_lines_read && col_num == 0) {
|
||||
return CompilationError::from(ParserError::IncompleteReduction(line_num, col_num));
|
||||
return CompilationError::from(ParserError::IncompleteReduction(err.err_src()));
|
||||
}
|
||||
}
|
||||
|
||||
CompilationError::from(err)
|
||||
}
|
||||
|
||||
impl FocusedHeap {
|
||||
pub fn to_machine_heap(mut self, machine_st: &mut MachineState) -> TermWriteResult {
|
||||
let heap_len = machine_st.heap.len();
|
||||
machine_st.heap.extend(copy_and_align_iter(self.heap.drain(..), 0, heap_len as i64));
|
||||
|
||||
let mut var_locs = VarLocs::default();
|
||||
|
||||
for (var_loc, var_ptrs) in self.var_locs.drain(..) {
|
||||
var_locs.insert(var_loc + heap_len, var_ptrs);
|
||||
}
|
||||
|
||||
TermWriteResult {
|
||||
heap_loc: self.focus + heap_len,
|
||||
var_locs,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl MachineState {
|
||||
pub(crate) fn read(
|
||||
pub(crate) fn read<R: CharRead>(
|
||||
&mut self,
|
||||
inner: R,
|
||||
op_dir: &OpDir,
|
||||
) -> Result<(FocusedHeap, usize), ParserError> {
|
||||
let mut parser = Parser::new(inner, self);
|
||||
let op_dir = CompositeOpDir::new(op_dir, None);
|
||||
|
||||
let term_result = parser.read_term(&op_dir, Tokens::Default);
|
||||
let lines_read = parser.lines_read();
|
||||
|
||||
term_result.map(|term| (term, lines_read))
|
||||
}
|
||||
|
||||
pub(crate) fn read_to_heap(
|
||||
&mut self,
|
||||
mut inner: Stream,
|
||||
op_dir: &OpDir,
|
||||
) -> Result<TermWriteResult, CompilationError> {
|
||||
let (term, num_lines_read) = {
|
||||
let prior_num_lines_read = inner.lines_read();
|
||||
let mut parser = Parser::new(inner, self);
|
||||
let op_dir = CompositeOpDir::new(op_dir, None);
|
||||
|
||||
parser.add_lines_read(prior_num_lines_read);
|
||||
|
||||
let term = parser
|
||||
.read_term(&op_dir, Tokens::Default)
|
||||
.map_err(|err| error_after_read_term(err, prior_num_lines_read, &parser))?; // CompilationError::from
|
||||
|
||||
(term, parser.lines_read() - prior_num_lines_read)
|
||||
let prior_num_lines_read = inner.lines_read();
|
||||
let term = match self.read(inner, op_dir) {
|
||||
Ok((term, num_lines_read)) => {
|
||||
inner.add_lines_read(num_lines_read);
|
||||
term
|
||||
}
|
||||
Err(e) => {
|
||||
return Err(error_after_read_term(e, prior_num_lines_read));
|
||||
}
|
||||
};
|
||||
|
||||
inner.add_lines_read(num_lines_read);
|
||||
write_term_to_heap(&term, &mut self.heap, &self.atom_tbl)
|
||||
Ok(term.to_machine_heap(self))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -279,7 +295,6 @@ impl CharRead for ReadlineStream {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn consume(&mut self, nread: usize) {
|
||||
self.pending_input.consume(nread);
|
||||
@@ -291,199 +306,8 @@ impl CharRead for ReadlineStream {
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn write_term_to_heap(
|
||||
term: &Term,
|
||||
heap: &mut Heap,
|
||||
atom_tbl: &AtomTable,
|
||||
) -> Result<TermWriteResult, CompilationError> {
|
||||
let term_writer = TermWriter::new(heap, atom_tbl);
|
||||
term_writer.write_term_to_heap(term)
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct TermWriter<'a, 'b> {
|
||||
heap: &'a mut Heap,
|
||||
atom_tbl: &'b AtomTable,
|
||||
queue: SubtermDeque,
|
||||
var_dict: HeapVarDict,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct TermWriteResult {
|
||||
pub heap_loc: usize,
|
||||
pub var_dict: HeapVarDict,
|
||||
}
|
||||
|
||||
impl<'a, 'b> TermWriter<'a, 'b> {
|
||||
#[inline]
|
||||
fn new(heap: &'a mut Heap, atom_tbl: &'b AtomTable) -> Self {
|
||||
TermWriter {
|
||||
heap,
|
||||
atom_tbl,
|
||||
queue: SubtermDeque::new(),
|
||||
var_dict: HeapVarDict::with_hasher(FxBuildHasher::default()),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn modify_head_of_queue(&mut self, term: &TermRef, h: usize) {
|
||||
if let Some((arity, site_h)) = self.queue.pop_front() {
|
||||
self.heap[site_h] = self.term_as_addr(term, h);
|
||||
|
||||
if arity > 1 {
|
||||
self.queue.push_front((arity - 1, site_h + 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn push_stub_addr(&mut self) {
|
||||
let h = self.heap.len();
|
||||
self.heap.push(heap_loc_as_cell!(h));
|
||||
}
|
||||
|
||||
fn term_as_addr(&mut self, term: &TermRef, h: usize) -> HeapCellValue {
|
||||
match term {
|
||||
&TermRef::Cons(..) => list_loc_as_cell!(h),
|
||||
&TermRef::AnonVar(_) | &TermRef::Var(..) => heap_loc_as_cell!(h),
|
||||
TermRef::CompleteString(_, _, src) => {
|
||||
if src.as_str().is_empty() {
|
||||
empty_list_as_cell!()
|
||||
} else if self.heap[h].get_tag() == HeapCellValueTag::CStr {
|
||||
heap_loc_as_cell!(h)
|
||||
} else {
|
||||
pstr_loc_as_cell!(h)
|
||||
}
|
||||
}
|
||||
&TermRef::PartialString(..) => pstr_loc_as_cell!(h),
|
||||
&TermRef::Literal(_, _, literal) => HeapCellValue::from(*literal),
|
||||
&TermRef::Clause(_, _, _, subterms) if subterms.is_empty() => heap_loc_as_cell!(h),
|
||||
&TermRef::Clause(..) => str_loc_as_cell!(h),
|
||||
}
|
||||
}
|
||||
|
||||
fn write_term_to_heap(mut self, term: &Term) -> Result<TermWriteResult, CompilationError> {
|
||||
let heap_loc = self.heap.len();
|
||||
|
||||
for term in breadth_first_iter(term, RootIterationPolicy::Iterated) {
|
||||
let h = self.heap.len();
|
||||
|
||||
match &term {
|
||||
&TermRef::Cons(Level::Root, ..) => {
|
||||
self.queue.push_back((2, h + 1));
|
||||
self.heap.push(list_loc_as_cell!(h + 1));
|
||||
|
||||
self.push_stub_addr();
|
||||
self.push_stub_addr();
|
||||
|
||||
continue;
|
||||
}
|
||||
&TermRef::Cons(..) => {
|
||||
self.queue.push_back((2, h));
|
||||
|
||||
self.push_stub_addr();
|
||||
self.push_stub_addr();
|
||||
}
|
||||
&TermRef::Clause(Level::Root, _, name, subterms) => {
|
||||
if subterms.len() > MAX_ARITY {
|
||||
return Err(CompilationError::ExceededMaxArity);
|
||||
}
|
||||
|
||||
self.heap.push(if subterms.is_empty() {
|
||||
heap_loc_as_cell!(heap_loc + 1)
|
||||
} else {
|
||||
str_loc_as_cell!(heap_loc + 1)
|
||||
});
|
||||
|
||||
self.queue.push_back((subterms.len(), h + 2));
|
||||
let named = atom_as_cell!(name, subterms.len());
|
||||
|
||||
self.heap.push(named);
|
||||
|
||||
for _ in 0..subterms.len() {
|
||||
self.push_stub_addr();
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
&TermRef::Clause(_, _, name, subterms) => {
|
||||
self.queue.push_back((subterms.len(), h + 1));
|
||||
let named = atom_as_cell!(name, subterms.len());
|
||||
|
||||
self.heap.push(named);
|
||||
|
||||
for _ in 0..subterms.len() {
|
||||
self.push_stub_addr();
|
||||
}
|
||||
}
|
||||
&TermRef::AnonVar(Level::Root) | TermRef::Literal(Level::Root, ..) => {
|
||||
let addr = self.term_as_addr(&term, h);
|
||||
self.heap.push(addr);
|
||||
}
|
||||
&TermRef::Var(Level::Root, _, ref var_ptr) => {
|
||||
let addr = self.term_as_addr(&term, h);
|
||||
self.var_dict.insert(VarKey::VarPtr(var_ptr.clone()), addr);
|
||||
self.heap.push(addr);
|
||||
}
|
||||
&TermRef::AnonVar(_) => {
|
||||
if let Some((arity, site_h)) = self.queue.pop_front() {
|
||||
self.var_dict
|
||||
.insert(VarKey::AnonVar(h), heap_loc_as_cell!(site_h));
|
||||
|
||||
if arity > 1 {
|
||||
self.queue.push_front((arity - 1, site_h + 1));
|
||||
}
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
TermRef::CompleteString(_, _, src) => {
|
||||
let src = src.as_str().to_owned();
|
||||
put_complete_string(self.heap, &src, self.atom_tbl);
|
||||
}
|
||||
&TermRef::PartialString(lvl, _, src, _) => {
|
||||
if let Level::Root = lvl {
|
||||
// Var tags can't refer directly to partial strings,
|
||||
// so a PStrLoc cell must be pushed.
|
||||
self.heap.push(pstr_loc_as_cell!(heap_loc + 1));
|
||||
}
|
||||
|
||||
allocate_pstr(self.heap, src.as_str(), self.atom_tbl);
|
||||
|
||||
let h = self.heap.len();
|
||||
self.queue.push_back((1, h - 1));
|
||||
|
||||
if let Level::Root = lvl {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
TermRef::Var(.., var) => {
|
||||
if let Some((arity, site_h)) = self.queue.pop_front() {
|
||||
let var_key = VarKey::VarPtr(var.clone());
|
||||
|
||||
if let Some(addr) = self.var_dict.get(&var_key).cloned() {
|
||||
self.heap[site_h] = addr;
|
||||
} else {
|
||||
self.var_dict.insert(var_key, heap_loc_as_cell!(site_h));
|
||||
}
|
||||
|
||||
if arity > 1 {
|
||||
self.queue.push_front((arity - 1, site_h + 1));
|
||||
}
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
_ => {}
|
||||
};
|
||||
|
||||
self.modify_head_of_queue(&term, h);
|
||||
}
|
||||
|
||||
Ok(TermWriteResult {
|
||||
heap_loc,
|
||||
var_dict: self.var_dict,
|
||||
})
|
||||
}
|
||||
pub var_locs: VarLocs,
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user