compact lists of characters to partial strings in read_term_from_heap (#1452, #1453)

This commit is contained in:
Mark Thom
2022-05-01 23:13:48 -06:00
parent 789f662ec8
commit 0f502fff84
8 changed files with 116 additions and 91 deletions

View File

@@ -79,7 +79,7 @@ impl<'a> ArithInstructionIterator<'a> {
)),
}?,
Term::Literal(cell, cons) => TermIterState::Literal(Level::Shallow, cell, cons),
Term::Cons(..) | Term::PartialString(..) => {
Term::Cons(..) | Term::PartialString(..) | Term::CompleteString(..) => {
return Err(ArithmeticError::NonEvaluableFunctor(
Literal::Atom(atom!(".")),
2,

View File

@@ -324,7 +324,8 @@ impl<'b> CodeGenerator<'b> {
}
&Term::Cons(ref cell, ..) |
&Term::Clause(ref cell, ..) |
Term::PartialString(ref cell, ..) => {
Term::PartialString(ref cell, ..) |
Term::CompleteString(ref cell, ..) => {
self.marker.mark_non_var::<Target>(Level::Deep, term_loc, cell, target);
target.push(Target::clause_arg_to_instr(cell.get()));
}
@@ -383,13 +384,14 @@ impl<'b> CodeGenerator<'b> {
}
TermRef::PartialString(lvl, cell, string, tail) => {
self.marker.mark_non_var::<Target>(lvl, term_loc, cell, &mut target);
let atom = self.atom_tbl.build_with(&string);
if let Some(tail) = tail {
target.push(Target::to_pstr(lvl, string, cell.get(), true));
self.subterm_to_instr::<Target>(tail, term_loc, is_exposed, &mut target);
} else {
target.push(Target::to_pstr(lvl, string, cell.get(), false));
}
target.push(Target::to_pstr(lvl, atom, cell.get(), true));
self.subterm_to_instr::<Target>(tail, term_loc, is_exposed, &mut target);
}
TermRef::CompleteString(lvl, cell, atom) => {
self.marker.mark_non_var::<Target>(lvl, term_loc, cell, &mut target);
target.push(Target::to_pstr(lvl, atom, cell.get(), false));
}
TermRef::Var(lvl @ Level::Shallow, cell, ref var) if var.as_str() == "!" => {
if self.marker.is_unbound(var.clone()) {
@@ -550,7 +552,8 @@ impl<'b> CodeGenerator<'b> {
&Term::AnonVar |
&Term::Clause(..) |
&Term::Cons(..) |
&Term::PartialString(..) => {
&Term::PartialString(..) |
&Term::CompleteString(..) => {
code.push(instr!("$fail", 0));
}
&Term::Literal(_, Literal::String(_)) => {
@@ -577,6 +580,7 @@ impl<'b> CodeGenerator<'b> {
&Term::Clause(..) |
&Term::Cons(..) |
&Term::PartialString(..) |
&Term::CompleteString(..) |
&Term::Literal(_, Literal::String(..)) => {
code.push(instr!("$succeed", 0));
}
@@ -702,7 +706,8 @@ impl<'b> CodeGenerator<'b> {
&Term::Literal(..) |
&Term::Clause(..) |
&Term::Cons(..) |
&Term::PartialString(..) => {
&Term::PartialString(..) |
&Term::CompleteString(..) => {
code.push(instr!("$fail", 0));
}
&Term::AnonVar => {

View File

@@ -17,7 +17,8 @@ pub(crate) enum TermRef<'a> {
Cons(Level, &'a Cell<RegType>, &'a Term, &'a Term),
Literal(Level, &'a Cell<RegType>, &'a Literal),
Clause(Level, &'a Cell<RegType>, ClauseType, &'a Vec<Term>),
PartialString(Level, &'a Cell<RegType>, Atom, &'a Option<Box<Term>>),
PartialString(Level, &'a Cell<RegType>, &'a String, &'a Box<Term>),
CompleteString(Level, &'a Cell<RegType>, Atom),
Var(Level, &'a Cell<VarReg>, Rc<String>),
}
@@ -28,8 +29,9 @@ impl<'a> TermRef<'a> {
| TermRef::Cons(lvl, ..)
| TermRef::Literal(lvl, ..)
| TermRef::Var(lvl, ..)
| TermRef::Clause(lvl, ..) => lvl,
TermRef::PartialString(lvl, ..) => lvl,
| TermRef::Clause(lvl, ..)
| TermRef::CompleteString(lvl, ..)
| TermRef::PartialString(lvl, ..) => lvl,
}
}
}
@@ -41,8 +43,9 @@ pub(crate) enum TermIterState<'a> {
Clause(Level, usize, &'a Cell<RegType>, ClauseType, &'a Vec<Term>),
InitialCons(Level, &'a Cell<RegType>, &'a Term, &'a Term),
FinalCons(Level, &'a Cell<RegType>, &'a Term, &'a Term),
InitialPartialString(Level, &'a Cell<RegType>, Atom, &'a Option<Box<Term>>),
FinalPartialString(Level, &'a Cell<RegType>, Atom, &'a Option<Box<Term>>),
InitialPartialString(Level, &'a Cell<RegType>, &'a String, &'a Box<Term>),
FinalPartialString(Level, &'a Cell<RegType>, &'a String, &'a Box<Term>),
CompleteString(Level, &'a Cell<RegType>, Atom),
Var(Level, &'a Cell<VarReg>, Rc<String>),
}
@@ -59,7 +62,10 @@ impl<'a> TermIterState<'a> {
}
Term::Literal(cell, constant) => TermIterState::Literal(lvl, cell, constant),
Term::PartialString(cell, string_buf, tail) => {
TermIterState::InitialPartialString(lvl, cell, *string_buf, tail)
TermIterState::InitialPartialString(lvl, cell, string_buf, tail)
}
Term::CompleteString(cell, atom) => {
TermIterState::CompleteString(lvl, cell, *atom)
}
Term::Var(cell, var) => TermIterState::Var(lvl, cell, var.clone()),
}
@@ -89,7 +95,8 @@ impl<'a> QueryIterator<'a> {
fn from_term(term: &'a Term) -> Self {
let state = match term {
Term::AnonVar | Term::Cons(..) | Term::Literal(..) | Term::PartialString(..) => {
Term::AnonVar | Term::Cons(..) | Term::Literal(..) |
Term::PartialString(..) | Term::CompleteString(..) => {
return QueryIterator {
state_stack: vec![],
}
@@ -196,13 +203,13 @@ impl<'a> Iterator for QueryIterator<'a> {
}
TermIterState::InitialPartialString(lvl, cell, string, tail) => {
self.state_stack.push(TermIterState::FinalPartialString(lvl, cell, string, tail));
if let Some(tail) = tail {
self.push_subterm(lvl.child_level(), tail);
}
self.push_subterm(lvl.child_level(), tail);
}
TermIterState::FinalPartialString(lvl, cell, string, tail) => {
return Some(TermRef::PartialString(lvl, cell, string, tail));
TermIterState::FinalPartialString(lvl, cell, atom, tail) => {
return Some(TermRef::PartialString(lvl, cell, atom, tail));
}
TermIterState::CompleteString(lvl, cell, atom) => {
return Some(TermRef::CompleteString(lvl, cell, atom));
}
TermIterState::FinalCons(lvl, cell, head, tail) => {
return Some(TermRef::Cons(lvl, cell, head, tail));
@@ -259,12 +266,19 @@ impl<'a> FactIterator<'a> {
head.as_ref(),
tail.as_ref(),
)],
Term::PartialString(cell, string_buf, tail_opt) => {
Term::PartialString(cell, string_buf, tail) => {
vec![TermIterState::InitialPartialString(
Level::Root,
cell,
*string_buf,
tail_opt,
string_buf,
tail,
)]
}
Term::CompleteString(cell, atom) => {
vec![TermIterState::CompleteString(
Level::Root,
cell,
*atom,
)]
}
Term::Literal(cell, constant) => {
@@ -307,12 +321,12 @@ impl<'a> Iterator for FactIterator<'a> {
return Some(TermRef::Cons(lvl, cell, head, tail));
}
TermIterState::InitialPartialString(lvl, cell, string_buf, tail_opt) => {
if let Some(tail) = tail_opt {
self.push_subterm(Level::Deep, tail);
}
return Some(TermRef::PartialString(lvl, cell, string_buf, tail_opt));
TermIterState::InitialPartialString(lvl, cell, string_buf, tail) => {
self.push_subterm(Level::Deep, tail);
return Some(TermRef::PartialString(lvl, cell, string_buf, tail));
}
TermIterState::CompleteString(lvl, cell, atom) => {
return Some(TermRef::CompleteString(lvl, cell, atom));
}
TermIterState::Literal(lvl, cell, constant) => {
return Some(TermRef::Literal(lvl, cell, constant))

View File

@@ -8,6 +8,7 @@
]).
:- use_module(library(error)).
:- use_module(library(iso_ext)).
:- use_module(library(lists), [append/3, member/2]).
:- use_module(library(loader), [strip_module/3]).

View File

@@ -485,10 +485,21 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
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();
term_stack.push(Term::Cons(Cell::default(), Box::new(head), Box::new(tail)));
match as_partial_string(head, tail) {
Ok((string, Some(tail))) => {
term_stack.push(Term::PartialString(Cell::default(), string, tail));
}
Ok((string, None)) => {
let atom = machine_st.atom_tbl.build_with(&string);
term_stack.push(Term::CompleteString(Cell::default(), atom));
}
Err(cons_term) => term_stack.push(cons_term),
}
}
(HeapCellValueTag::Var | HeapCellValueTag::AttrVar | HeapCellValueTag::StackVar, h) => {
let offset_string = format!("_{}", h);
@@ -509,31 +520,27 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
term_stack.push(Term::Clause(Cell::default(), name, subterms));
}
}
(HeapCellValueTag::PStr, string) => {
(HeapCellValueTag::PStr, atom) => {
let tail = term_stack.pop().unwrap();
if let Term::Literal(_, Literal::Atom(atom!("[]"))) = &tail {
term_stack.push(Term::PartialString(
Cell::default(),
string,
None,
));
term_stack.push(Term::CompleteString(Cell::default(), atom));
} else {
term_stack.push(Term::PartialString(
Cell::default(),
string,
Some(Box::new(tail)),
atom.as_str().to_owned(),
Box::new(tail),
));
}
}
(HeapCellValueTag::PStrLoc, h) => {
let string = cell_as_atom_cell!(iter.heap[h]).get_name();
let atom = cell_as_atom_cell!(iter.heap[h]).get_name();
let tail = term_stack.pop().unwrap();
term_stack.push(Term::PartialString(
Cell::default(),
string,
Some(Box::new(tail)),
atom.as_str().to_owned(),
Box::new(tail),
));
}
_ => {

View File

@@ -541,11 +541,7 @@ impl fmt::Display for Literal {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
Literal::Atom(ref atom) => {
// if atom.as_str().chars().any(|c| "`.$'\" ".contains(c)) {
// write!(f, "'{}'", atom)
// } else {
write!(f, "{}", atom.flat_index())
// }
}
Literal::Char(c) => write!(f, "'{}'", *c as u32),
Literal::Fixnum(n) => write!(f, "{}", n.get_num()),
@@ -553,7 +549,6 @@ impl fmt::Display for Literal {
Literal::Rational(ref n) => write!(f, "{}", n),
Literal::Float(ref n) => write!(f, "{}", *n),
Literal::String(ref s) => write!(f, "\"{}\"", s.as_str()),
// Literal::Usize(integer) => write!(f, "u{}", integer),
}
}
}
@@ -573,7 +568,10 @@ pub enum Term {
Clause(Cell<RegType>, Atom, Vec<Term>),
Cons(Cell<RegType>, Box<Term>, Box<Term>),
Literal(Cell<RegType>, Literal),
PartialString(Cell<RegType>, Atom, Option<Box<Term>>),
// PartialString wraps a String in anticipation of it absorbing
// other PartialString variants in as_partial_string.
PartialString(Cell<RegType>, String, Box<Term>),
CompleteString(Cell<RegType>, Atom),
Var(Cell<VarReg>, Rc<String>),
}

View File

@@ -49,11 +49,10 @@ struct TokenDesc {
spec: u32,
}
fn is_partial_string(
pub(crate) fn as_partial_string(
head: Term,
mut tail: Term,
atom_tbl: &mut AtomTable,
) -> Result<(Atom, Option<Box<Term>>), Term> {
) -> Result<(String, Option<Box<Term>>), Term> {
let mut string = match &head {
Term::Literal(_, Literal::Atom(atom)) => {
if let Some(c) = atom.as_char() {
@@ -92,6 +91,15 @@ fn is_partial_string(
tail_ref = succ;
}
Term::PartialString(_, pstr, tail) => {
string += &pstr;
tail_ref = tail;
}
Term::CompleteString(_, cstr) => {
string += cstr.as_str();
tail = Term::Literal(Cell::default(), Literal::Atom(atom!("[]")));
break;
}
tail_ref => {
tail = mem::replace(tail_ref, Term::AnonVar);
break;
@@ -101,21 +109,17 @@ fn is_partial_string(
match &tail {
Term::AnonVar | Term::Var(..) => {
let pstr_atom = atom_tbl.build_with(&string);
Ok((pstr_atom, Some(Box::new(tail))))
Ok((string, Some(Box::new(tail))))
}
Term::Literal(_, Literal::Atom(atom!("[]"))) => {
let pstr_atom = atom_tbl.build_with(&string);
Ok((pstr_atom, None))
Ok((string, None))
}
Term::Literal(_, Literal::String(tail)) => {
string += tail.as_str();
let pstr_atom = atom_tbl.build_with(&string);
Ok((pstr_atom, None))
Ok((string, None))
}
_ => {
let pstr_atom = atom_tbl.build_with(&string);
Ok((pstr_atom, Some(Box::new(tail))))
Ok((string, Some(Box::new(tail))))
}
}
}
@@ -412,7 +416,7 @@ impl<'a, R: CharRead> Parser<'a, R> {
TokenType::Term
}
Token::Literal(Literal::String(s)) if self.lexer.machine_st.flags.double_quotes.is_chars() => {
self.terms.push(Term::PartialString(Cell::default(), s, None));
self.terms.push(Term::CompleteString(Cell::default(), s));
TokenType::Term
}
Token::Literal(c) => {
@@ -564,24 +568,19 @@ impl<'a, R: CharRead> Parser<'a, R> {
let head = subterms.pop().unwrap();
self.terms.push(
match is_partial_string(head, tail, &mut self.lexer.machine_st.atom_tbl) {
Ok((string_buf, tail_opt)) => {
Term::PartialString(Cell::default(), string_buf, tail_opt)
match as_partial_string(head, tail) {
Ok((string_buf, Some(tail))) => {
Term::PartialString(Cell::default(), string_buf, tail)
}
Ok((string_buf, None)) => {
let atom = self.lexer.machine_st.atom_tbl.build_with(&string_buf);
Term::CompleteString(Cell::default(), atom)
}
Err(term) => term,
},
);
/*
self.terms.push(Term::Cons(
Cell::default(),
Box::new(head),
Box::new(tail),
));
*/
} else {
self.terms
.push(Term::Clause(Cell::default(), name, subterms));
self.terms.push(Term::Clause(Cell::default(), name, subterms));
}
if let Some(&mut TokenDesc {
@@ -741,9 +740,13 @@ impl<'a, R: CharRead> Parser<'a, R> {
self.terms.push(match list {
Term::Cons(_, head, tail) => {
match is_partial_string(*head, *tail, &mut self.lexer.machine_st.atom_tbl) {
Ok((string_buf, tail_opt)) => {
Term::PartialString(Cell::default(), string_buf, tail_opt)
match as_partial_string(*head, *tail) {
Ok((string_buf, Some(tail))) => {
Term::PartialString(Cell::default(), string_buf, tail)
}
Ok((string_buf, None)) => {
let atom = self.lexer.machine_st.atom_tbl.build_with(&string_buf);
Term::CompleteString(Cell::default(), atom)
}
Err(term) => term,
}

View File

@@ -286,7 +286,7 @@ impl<'a, 'b> TermWriter<'a, 'b> {
match term {
&TermRef::Cons(..) => list_loc_as_cell!(h),
&TermRef::AnonVar(_) | &TermRef::Var(..) => heap_loc_as_cell!(h),
&TermRef::PartialString(_, _, ref src, None) =>
&TermRef::CompleteString(_, _, ref src) =>
if src.as_str().is_empty() {
empty_list_as_cell!()
} else if self.heap[h].get_tag() == HeapCellValueTag::CStr {
@@ -369,20 +369,17 @@ impl<'a, 'b> TermWriter<'a, 'b> {
continue;
}
&TermRef::PartialString(lvl, _, ref src, tail) => {
if tail.is_some() {
allocate_pstr(self.heap, src.as_str(), self.atom_tbl);
} else {
put_complete_string(self.heap, src.as_str(), self.atom_tbl);
}
&TermRef::CompleteString(_, _, ref src) => {
put_complete_string(self.heap, src.as_str(), self.atom_tbl);
}
&TermRef::PartialString(lvl, _, ref src, _) => {
allocate_pstr(self.heap, src.as_str(), self.atom_tbl);
if tail.is_some() {
let h = self.heap.len();
self.queue.push_back((1, h - 1));
let h = self.heap.len();
self.queue.push_back((1, h - 1));
if let Level::Root = lvl {
continue;
}
if let Level::Root = lvl {
continue;
}
}
&TermRef::Var(_, _, ref var) => {