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::Literal(cell, cons) => TermIterState::Literal(Level::Shallow, cell, cons),
Term::Cons(..) | Term::PartialString(..) => { Term::Cons(..) | Term::PartialString(..) | Term::CompleteString(..) => {
return Err(ArithmeticError::NonEvaluableFunctor( return Err(ArithmeticError::NonEvaluableFunctor(
Literal::Atom(atom!(".")), Literal::Atom(atom!(".")),
2, 2,

View File

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

View File

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

View File

@@ -8,6 +8,7 @@
]). ]).
:- use_module(library(error)). :- use_module(library(error)).
:- use_module(library(iso_ext)).
:- use_module(library(lists), [append/3, member/2]). :- use_module(library(lists), [append/3, member/2]).
:- use_module(library(loader), [strip_module/3]). :- 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, read_heap_cell!(addr,
(HeapCellValueTag::Lis) => { (HeapCellValueTag::Lis) => {
use crate::parser::parser::as_partial_string;
let tail = term_stack.pop().unwrap(); let tail = term_stack.pop().unwrap();
let head = 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) => { (HeapCellValueTag::Var | HeapCellValueTag::AttrVar | HeapCellValueTag::StackVar, h) => {
let offset_string = format!("_{}", 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)); term_stack.push(Term::Clause(Cell::default(), name, subterms));
} }
} }
(HeapCellValueTag::PStr, string) => { (HeapCellValueTag::PStr, atom) => {
let tail = term_stack.pop().unwrap(); let tail = term_stack.pop().unwrap();
if let Term::Literal(_, Literal::Atom(atom!("[]"))) = &tail { if let Term::Literal(_, Literal::Atom(atom!("[]"))) = &tail {
term_stack.push(Term::PartialString( term_stack.push(Term::CompleteString(Cell::default(), atom));
Cell::default(),
string,
None,
));
} else { } else {
term_stack.push(Term::PartialString( term_stack.push(Term::PartialString(
Cell::default(), Cell::default(),
string, atom.as_str().to_owned(),
Some(Box::new(tail)), Box::new(tail),
)); ));
} }
} }
(HeapCellValueTag::PStrLoc, h) => { (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(); let tail = term_stack.pop().unwrap();
term_stack.push(Term::PartialString( term_stack.push(Term::PartialString(
Cell::default(), Cell::default(),
string, atom.as_str().to_owned(),
Some(Box::new(tail)), Box::new(tail),
)); ));
} }
_ => { _ => {

View File

@@ -541,11 +541,7 @@ impl fmt::Display for Literal {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self { match self {
Literal::Atom(ref atom) => { Literal::Atom(ref atom) => {
// if atom.as_str().chars().any(|c| "`.$'\" ".contains(c)) {
// write!(f, "'{}'", atom)
// } else {
write!(f, "{}", atom.flat_index()) write!(f, "{}", atom.flat_index())
// }
} }
Literal::Char(c) => write!(f, "'{}'", *c as u32), Literal::Char(c) => write!(f, "'{}'", *c as u32),
Literal::Fixnum(n) => write!(f, "{}", n.get_num()), 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::Rational(ref n) => write!(f, "{}", n),
Literal::Float(ref n) => write!(f, "{}", *n), Literal::Float(ref n) => write!(f, "{}", *n),
Literal::String(ref s) => write!(f, "\"{}\"", s.as_str()), 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>), Clause(Cell<RegType>, Atom, Vec<Term>),
Cons(Cell<RegType>, Box<Term>, Box<Term>), Cons(Cell<RegType>, Box<Term>, Box<Term>),
Literal(Cell<RegType>, Literal), 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>), Var(Cell<VarReg>, Rc<String>),
} }

View File

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

View File

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