target.push(Target::to_void(1));
}
- fn subterm_to_instr<Target>(
+ fn deep_var_instr<Target: CompilationTarget<'a>>(
+ &mut self,
+ cell: &'a Cell<VarReg>,
+ var: &'a Rc<Var>,
+ term_loc: GenContext,
+ is_exposed: bool,
+ target: &mut Vec<Target>,
+ ) {
+ if is_exposed || self.get_var_count(var.as_ref()) > 1 {
+ self.marker.mark_var(var.clone(), Level::Deep, cell, term_loc, target);
+ } else {
+ Self::add_or_increment_void_instr(target);
+ }
+ }
+
+ fn subterm_to_instr<Target: CompilationTarget<'a>>(
&mut self,
subterm: &'a Term,
term_loc: GenContext,
is_exposed: bool,
target: &mut Vec<Target>,
- ) where
- Target: CompilationTarget<'a>,
- {
+ ) {
match subterm {
&Term::AnonVar if is_exposed => {
- self.marker.mark_anon_var(Level::Deep, term_loc, target)
+ self.marker.mark_anon_var(Level::Deep, term_loc, target);
+ }
+ &Term::AnonVar => {
+ Self::add_or_increment_void_instr(target);
}
- &Term::AnonVar => Self::add_or_increment_void_instr(target),
&Term::Cons(ref cell, _, _) | &Term::Clause(ref cell, _, _, _) => {
- self.marker
- .mark_non_var(Level::Deep, term_loc, cell, target);
+ self.marker.mark_non_var(Level::Deep, term_loc, cell, target);
target.push(Target::clause_arg_to_instr(cell.get()));
}
&Term::Constant(_, ref constant) => {
- target.push(Target::constant_subterm(constant.clone()))
+ target.push(Target::constant_subterm(constant.clone()));
}
&Term::Var(ref cell, ref var) => {
- if is_exposed || self.get_var_count(var) > 1 {
- self.marker
- .mark_var(var.clone(), Level::Deep, cell, term_loc, target);
- } else {
- Self::add_or_increment_void_instr(target);
- }
+ self.deep_var_instr(cell, var, term_loc, is_exposed, target);
}
};
}
- fn compile_target<Target, Iter>(
+ fn compile_target<Target, Iter>(
&mut self,
iter: Iter,
term_loc: GenContext,
for term in iter {
match term {
+ TermRef::AnonVar(lvl @ Level::Shallow) => {
+ if let GenContext::Head = term_loc {
+ self.marker.advance_arg();
+ } else {
+ self.marker.mark_anon_var(lvl, term_loc, &mut target);
+ }
+ }
TermRef::Clause(lvl, cell, ct, terms) => {
self.marker.mark_non_var(lvl, term_loc, cell, &mut target);
target.push(Target::to_structure(ct, terms.len(), cell.get()));
self.subterm_to_instr(head, term_loc, is_exposed, &mut target);
self.subterm_to_instr(tail, term_loc, is_exposed, &mut target);
}
+ TermRef::Constant(lvl @ Level::Shallow, cell, Constant::String(ref string)) => {
+ self.marker.mark_non_var(lvl, term_loc, cell, &mut target);
+ target.push(Target::to_pstr(lvl, string.to_string(), cell.get(), false));
+ }
TermRef::Constant(lvl @ Level::Shallow, cell, constant) => {
self.marker.mark_non_var(lvl, term_loc, cell, &mut target);
target.push(Target::to_constant(lvl, constant.clone(), cell.get()));
}
- TermRef::AnonVar(lvl @ Level::Shallow) => {
- if let GenContext::Head = term_loc {
- self.marker.advance_arg();
+ TermRef::PartialString(lvl, cell, string, tail) => {
+ self.marker.mark_non_var(lvl, term_loc, cell, &mut target);
+
+ if let Some(tail) = tail {
+ target.push(Target::to_pstr(lvl, string, cell.get(), true));
+ self.subterm_to_instr(tail, term_loc, is_exposed, &mut target);
} else {
- self.marker.mark_anon_var(lvl, term_loc, &mut target);
+ target.push(Target::to_pstr(lvl, string, cell.get(), false));
}
}
TermRef::Var(lvl @ Level::Shallow, cell, ref var) if var.as_str() == "!" => {
}
}
- self.marker
- .mark_var(var.clone(), lvl, cell, term_loc, &mut target);
+ self.marker.mark_var(var.clone(), lvl, cell, term_loc, &mut target);
}
TermRef::Var(lvl @ Level::Shallow, cell, var) => {
- self.marker
- .mark_var(var.clone(), lvl, cell, term_loc, &mut target)
+ self.marker.mark_var(var.clone(), lvl, cell, term_loc, &mut target);
+ }
+ _ => {
}
- _ => {}
};
}
self.state_stack.push(TokenOrRedirect::CompositeRedirect(max_depth, left_directed_op));
self.state_stack.push(TokenOrRedirect::Op(ct.name(), spec));
} else {
- // if is_infix!(spec.assoc())
match ct.name().as_str() {
"|" => {
self.format_bar_separator_op(iter, max_depth, ct.name(), spec);
mut max_depth: usize,
h: usize,
n: usize,
- )
- {
+ ) {
iter.stack().pop();
iter.stack().pop();
let mut heap_pstr_iter =
self.machine_st.heap_pstr_iter(Addr::PStrLocation(h, n));
- let mut buf = String::new();
-
- while let Some(Some(c)) = heap_pstr_iter.next() {
- buf.push(c);
- }
-
- let end_addr =
- if let &HeapCellValue::PartialString(_, has_tail) = &self.machine_st.heap[h] {
- if has_tail {
- self.machine_st.store(self.machine_st.deref(heap_pstr_iter.focus()))
- } else {
- Addr::EmptyList
- }
- } else {
- unreachable!()
- };
+ let buf = heap_pstr_iter.to_string();
+ let end_addr = heap_pstr_iter.focus();
- if let Addr::EmptyList = end_addr {
+ if Addr::EmptyList == end_addr {
if !self.machine_st.flags.double_quotes.is_codes() {
self.push_char('"');
t: usize,
) -> MachineStub {
let at_stub = at.into_functor();
-
+
functor!(
name,
[aux(h, 0), integer(t)],
let at_2_stub = at_2.into_functor();
functor!(
- name,
+ name,
[aux(h, 0), aux(h, 1), integer(t)],
[at_1_stub, at_2_stub]
)
&ArithmeticInstruction::Gcd(ref at_1, ref at_2, t) => {
arith_instr_bin_functor(h, "gcd", at_1, at_2, t)
}
- &ArithmeticInstruction::Sign(ref at, t) => {
+ &ArithmeticInstruction::Sign(ref at, t) => {
arith_instr_unary_functor(h, "sign", at, t)
}
&ArithmeticInstruction::Cos(ref at, t) => {
pub enum FactInstruction {
GetConstant(Level, Constant, RegType),
GetList(Level, RegType),
+ GetPartialString(Level, String, RegType, bool),
GetStructure(ClauseType, usize, RegType),
GetValue(RegType, usize),
GetVariable(RegType, usize),
&FactInstruction::GetConstant(lvl, ref c, r) => {
let lvl_stub = lvl.into_functor();
let rt_stub = reg_type_into_functor(r);
-
+
functor!(
"get_constant",
[aux(h, 0), constant(h, c), aux(h, 1)],
[lvl_stub, rt_stub]
)
}
+ &FactInstruction::GetPartialString(lvl, ref s, r, has_tail) => {
+ let lvl_stub = lvl.into_functor();
+ let rt_stub = reg_type_into_functor(r);
+
+ functor!(
+ "get_partial_string",
+ [aux(h, 0), string(h, s), aux(h, 1), boolean(has_tail)],
+ [lvl_stub, rt_stub]
+ )
+ }
&FactInstruction::GetStructure(ref ct, arity, r) => {
let rt_stub = reg_type_into_functor(r);
}
&FactInstruction::UnifyLocalValue(r) => {
let rt_stub = reg_type_into_functor(r);
-
+
functor!(
"unify_local_value",
[aux(h, 0)],
}
&FactInstruction::UnifyValue(r) => {
let rt_stub = reg_type_into_functor(r);
-
+
functor!(
"unify_value",
[aux(h, 0)],
GetVariable(RegType, usize),
PutConstant(Level, Constant, RegType),
PutList(Level, RegType),
+ PutPartialString(Level, String, RegType, bool),
PutStructure(ClauseType, usize, RegType),
PutUnsafeValue(usize, usize),
PutValue(RegType, usize),
&QueryInstruction::PutList(lvl, r) => {
let lvl_stub = lvl.into_functor();
let rt_stub = reg_type_into_functor(r);
-
+
functor!(
"put_list",
[aux(h, 0), aux(h, 1)],
[lvl_stub, rt_stub]
)
}
+ &QueryInstruction::PutPartialString(lvl, ref s, r, has_tail) => {
+ let lvl_stub = lvl.into_functor();
+ let rt_stub = reg_type_into_functor(r);
+
+ functor!(
+ "put_partial_string",
+ [aux(h, 0), string(h, s), aux(h, 1), boolean(has_tail)],
+ [lvl_stub, rt_stub]
+ )
+ }
&QueryInstruction::PutStructure(ref ct, arity, r) => {
let rt_stub = reg_type_into_functor(r);
let rt_stub = reg_type_into_functor(r);
functor!(
- "put_value",
+ "put_value",
[aux(h, 0), integer(arg)],
[rt_stub]
)
}
&QueryInstruction::SetLocalValue(r) => {
let rt_stub = reg_type_into_functor(r);
-
+
functor!(
"set_local_value",
[aux(h, 0)],
Cons(Level, &'a Cell<RegType>, &'a Term, &'a Term),
Constant(Level, &'a Cell<RegType>, &'a Constant),
Clause(Level, &'a Cell<RegType>, ClauseType, &'a Vec<Box<Term>>),
+ PartialString(Level, &'a Cell<RegType>, String, Option<&'a Term>),
Var(Level, &'a Cell<VarReg>, Rc<Var>),
}
| TermRef::Constant(lvl, ..)
| TermRef::Var(lvl, ..)
| TermRef::Clause(lvl, ..) => lvl,
+ | TermRef::PartialString(lvl, ..) => lvl,
}
}
}
),
InitialCons(Level, &'a Cell<RegType>, &'a Term, &'a Term),
FinalCons(Level, &'a Cell<RegType>, &'a Term, &'a Term),
+ PartialString(Level, &'a Cell<RegType>, String, Option<&'a Term>),
Var(Level, &'a Cell<VarReg>, Rc<Var>),
}
+fn is_partial_string<'a>(
+ head: &'a Term,
+ mut tail: &'a Term,
+) -> Option<(String, Option<&'a Term>)>
+{
+ let mut string =
+ match head {
+ &Term::Constant(_, Constant::Atom(ref atom, _)) if atom.is_char() => {
+ atom.as_str().chars().next().unwrap().to_string()
+ }
+ &Term::Constant(_, Constant::Char(c)) => {
+ c.to_string()
+ }
+ _ => {
+ return None;
+ }
+ };
+
+ while let Term::Cons(_, ref head, ref succ) = tail {
+ match head.as_ref() {
+ &Term::Constant(_, Constant::Atom(ref atom, _)) if atom.is_char() => {
+ string.push(atom.as_str().chars().next().unwrap());
+ }
+ &Term::Constant(_, Constant::Char(c)) => {
+ string.push(c);
+ }
+ _ => {
+ return None;
+ }
+ };
+
+ tail = succ.as_ref();
+ }
+
+ match tail {
+ Term::AnonVar | Term::Var(..) => {
+ return Some((string, Some(tail)));
+ }
+ Term::Constant(_, Constant::EmptyList) => {
+ return Some((string, None));
+ }
+ _ => {
+ return None;
+ }
+ }
+}
+
impl<'a> TermIterState<'a> {
pub fn subterm_to_state(lvl: Level, term: &'a Term) -> TermIterState<'a> {
match term {
- &Term::AnonVar => TermIterState::AnonVar(lvl),
+ &Term::AnonVar => {
+ TermIterState::AnonVar(lvl)
+ }
&Term::Clause(ref cell, ref name, ref subterms, ref spec) => {
let ct = if let Some(spec) = spec {
ClauseType::Op(name.clone(), spec.clone(), CodeIndex::default())
&Term::Cons(ref cell, ref head, ref tail) => {
TermIterState::InitialCons(lvl, cell, head.as_ref(), tail.as_ref())
}
- &Term::Constant(ref cell, ref constant) => TermIterState::Constant(lvl, cell, constant),
- &Term::Var(ref cell, ref var) => TermIterState::Var(lvl, cell, var.clone()),
+ &Term::Constant(ref cell, ref constant) => {
+ TermIterState::Constant(lvl, cell, constant)
+ }
+ &Term::Var(ref cell, ref var) => {
+ TermIterState::Var(lvl, cell, var.clone())
+ }
}
}
}
QueryIterator {
state_stack: vec![state],
}
- }
+ }
&QueryTerm::Clause(ref cell, ref ct, ref terms, _) => {
let state = TermIterState::Clause(Level::Root, 0, cell, ct.clone(), terms);
QueryIterator {
fn next(&mut self) -> Option<Self::Item> {
while let Some(iter_state) = self.state_stack.pop() {
match iter_state {
- TermIterState::AnonVar(lvl) => return Some(TermRef::AnonVar(lvl)),
+ TermIterState::AnonVar(lvl) => {
+ return Some(TermRef::AnonVar(lvl));
+ }
TermIterState::Clause(lvl, child_num, cell, ct, child_terms) => {
if child_num == child_terms.len() {
match ct {
lvl => Some(TermRef::Clause(lvl, cell, ct, child_terms)),
}
}
- _ => return None,
+ _ => {
+ return None;
+ }
};
} else {
self.state_stack.push(TermIterState::Clause(
ct,
child_terms,
));
+
self.push_subterm(lvl.child_level(), child_terms[child_num].as_ref());
}
}
TermIterState::InitialCons(lvl, cell, head, tail) => {
- self.state_stack
- .push(TermIterState::FinalCons(lvl, cell, head, tail));
+ if let Some((string, tail)) = is_partial_string(head, tail) {
+ self.state_stack.push(TermIterState::PartialString(
+ lvl,
+ cell,
+ string,
+ tail,
+ ));
+
+ if let Some(tail) = tail {
+ self.push_subterm(lvl.child_level(), tail);
+ }
+ } else {
+ self.state_stack.push(TermIterState::FinalCons(lvl, cell, head, tail));
- self.push_subterm(lvl.child_level(), tail);
- self.push_subterm(lvl.child_level(), head);
+ self.push_subterm(lvl.child_level(), tail);
+ self.push_subterm(lvl.child_level(), head);
+ }
+ }
+ TermIterState::PartialString(lvl, cell, string, tail) => {
+ return Some(TermRef::PartialString(lvl, cell, string, tail));
}
TermIterState::FinalCons(lvl, cell, head, tail) => {
- return Some(TermRef::Cons(lvl, cell, head, tail))
+ return Some(TermRef::Cons(lvl, cell, head, tail));
}
TermIterState::Constant(lvl, cell, constant) => {
- return Some(TermRef::Constant(lvl, cell, constant))
+ return Some(TermRef::Constant(lvl, cell, constant));
+ }
+ TermIterState::Var(lvl, cell, var) => {
+ return Some(TermRef::Var(lvl, cell, var));
}
- TermIterState::Var(lvl, cell, var) => return Some(TermRef::Var(lvl, cell, var)),
};
}
impl<'a> FactIterator<'a> {
fn push_subterm(&mut self, lvl: Level, term: &'a Term) {
- self.state_queue
- .push_back(TermIterState::subterm_to_state(lvl, term));
+ self.state_queue.push_back(TermIterState::subterm_to_state(lvl, term));
}
pub fn from_rule_head_clause(terms: &'a Vec<Box<Term>>) -> Self {
fn new(term: &'a Term, iterable_root: bool) -> Self {
let states = match term {
- &Term::AnonVar => vec![TermIterState::AnonVar(Level::Root)],
+ &Term::AnonVar => {
+ vec![TermIterState::AnonVar(Level::Root)]
+ }
&Term::Clause(ref cell, ref name, ref terms, ref fixity) => {
let ct = ClauseType::from(name.clone(), terms.len(), fixity.clone());
vec![TermIterState::Clause(Level::Root, 0, cell, ct, terms)]
fn next(&mut self) -> Option<Self::Item> {
while let Some(state) = self.state_queue.pop_front() {
match state {
- TermIterState::AnonVar(lvl) => return Some(TermRef::AnonVar(lvl)),
+ TermIterState::AnonVar(lvl) => {
+ return Some(TermRef::AnonVar(lvl));
+ }
TermIterState::Clause(lvl, _, cell, ct, child_terms) => {
for child_term in child_terms {
self.push_subterm(lvl.child_level(), child_term);
};
}
TermIterState::InitialCons(lvl, cell, head, tail) => {
- self.push_subterm(Level::Deep, head);
- self.push_subterm(Level::Deep, tail);
+ if let Some((string, tail)) = is_partial_string(head, tail) {
+ if let Some(tail) = tail {
+ self.push_subterm(Level::Deep, tail);
+ }
- return Some(TermRef::Cons(lvl, cell, head, tail));
+ return Some(TermRef::PartialString(lvl, cell, string, tail));
+ } else {
+ self.push_subterm(Level::Deep, head);
+ self.push_subterm(Level::Deep, tail);
+
+ return Some(TermRef::Cons(lvl, cell, head, tail));
+ }
}
TermIterState::Constant(lvl, cell, constant) => {
return Some(TermRef::Constant(lvl, cell, constant))
}
- TermIterState::Var(lvl, cell, var) => return Some(TermRef::Var(lvl, cell, var)),
- _ => {}
+ TermIterState::Var(lvl, cell, var) => {
+ return Some(TermRef::Var(lvl, cell, var));
+ }
+ _ => {
+ }
}
}
_ => {
in_situ_code_dir.insert((name, arity), p);
}
- }
+ }
let mut cg = CodeGenerator::<DebrayAllocator>::new(non_counted_bt);
let mut decl_code = cg.compile_predicate(&decl.0)?;
}
#[inline]
- fn pop(&mut self) {
+ pub(crate)
+ fn put_complete_string(&mut self, s: &str) -> Addr {
+ let addr = self.allocate_pstr(s);
+ self.pop();
+
let h = self.h();
- if h > 0 {
- self.truncate(h - 1);
+ match &mut self[h - 1] {
+ &mut HeapCellValue::PartialString(_, ref mut has_tail) => {
+ *has_tail = false;
+ }
+ _ => {
+ unreachable!()
+ }
}
+
+ addr
}
#[inline]
if s.is_empty() {
Addr::EmptyList
} else {
- let addr = self.allocate_pstr(&s);
- self.pop();
-
- let h = self.h();
-
- match &mut self[h - 1] {
- &mut HeapCellValue::PartialString(_, ref mut has_tail) => {
- *has_tail = false;
- }
- _ => {
- unreachable!()
- }
- }
-
- addr
+ self.put_complete_string(&s)
}
}
Constant::Usize(n) => {
}
}
+ #[inline]
+ pub(crate)
+ fn pop(&mut self) {
+ let h = self.h();
+
+ if h > 0 {
+ self.truncate(h - 1);
+ }
+ }
+
#[inline]
pub(crate)
fn push(&mut self, val: HeapCellValue) -> usize {
let mut heap_pstr_iter =
machine_st.heap_pstr_iter(Addr::PStrLocation(h, n));
- let mut buf = String::new();
+ let buf = heap_pstr_iter.to_string();
+ let end_addr = heap_pstr_iter.focus();
- while let Some(Some(c)) = heap_pstr_iter.next() {
- buf.push(c);
- }
-
- let end_addr =
- machine_st.store(machine_st.deref(heap_pstr_iter.focus()));
-
- if let Addr::EmptyList = end_addr {
+ if end_addr == Addr::EmptyList {
Some(Constant::String(Rc::new(buf)))
} else {
None
use std::mem;
use std::ops::{Index, IndexMut};
-pub(crate)
-struct HeapPStrIter<'a> {
+pub(crate) struct HeapPStrIter<'a> {
focus: Addr,
machine_st: &'a MachineState,
seen: IndexSet<Addr>,
#[inline]
pub(crate)
fn focus(&'a self) -> Addr {
- self.focus
+ self.machine_st.store(self.machine_st.deref(self.focus))
}
+
+ #[inline]
+ pub(crate)
+ fn to_string(&mut self) -> String {
+ let mut buf = String::new();
+
+ while let Some(iteratee) = self.next() {
+ match iteratee {
+ PStrIteratee::Char(c) => {
+ buf.push(c);
+ }
+ PStrIteratee::PStrSegment(h, n) => {
+ match &self.machine_st.heap[h] {
+ HeapCellValue::PartialString(ref pstr, _) => {
+ buf += pstr.as_str_from(n);
+ }
+ _ => {
+ unreachable!()
+ }
+ }
+ }
+ }
+ }
+
+ buf
+ }
+}
+
+#[derive(Clone, Copy)]
+pub(crate) enum PStrIteratee {
+ Char(char),
+ PStrSegment(usize, usize),
}
impl<'a> Iterator for HeapPStrIter<'a> {
- type Item = Option<char>;
+ type Item = PStrIteratee;
fn next(&mut self) -> Option<Self::Item> {
let addr = self.machine_st.store(self.machine_st.deref(self.focus));
match addr {
Addr::PStrLocation(h, n) => {
- if let &HeapCellValue::PartialString(ref pstr, _) = &self.machine_st.heap[h] {
- if let Some(c) = pstr.range_from(n ..).next() {
- self.focus = Addr::PStrLocation(h, n + c.len_utf8());
- return Some(Some(c));
+ if let &HeapCellValue::PartialString(_, has_tail) = &self.machine_st.heap[h] {
+ self.focus = if has_tail {
+ Addr::HeapCell(h + 1)
} else {
- unreachable!()
- }
+ Addr::EmptyList
+ };
+
+ return Some(PStrIteratee::PStrSegment(h, n));
} else {
unreachable!()
}
Addr::Lis(l) => {
let addr = self.machine_st.store(self.machine_st.deref(Addr::HeapCell(l)));
- if let Addr::Char(c) = addr {
+ let opt_c = match addr {
+ Addr::Con(h) if self.machine_st.heap.atom_at(h) => {
+ if let HeapCellValue::Atom(ref atom, _) = &self.machine_st.heap[h] {
+ if atom.is_char() {
+ Some(atom.as_str().chars().next().unwrap())
+ } else {
+ None
+ }
+ } else {
+ unreachable!()
+ }
+ }
+ Addr::Char(c) => {
+ Some(c)
+ }
+ _ => {
+ None
+ }
+ };
+
+ if let Some(c) = opt_c {
self.focus = Addr::HeapCell(l + 1);
- return Some(Some(c));
+ return Some(PStrIteratee::Char(c));
} else {
return None;
}
}
Addr::EmptyList => {
self.focus = Addr::EmptyList;
- return Some(None);
+ return None;
}
_ => {
return None;
#[inline]
pub(super)
-fn compare_pstr<'a>(
- pstr_iter: HeapPStrIter<'a>,
- mut c_iter: impl Iterator<Item = char>,
-) -> bool {
- for opt_c in pstr_iter {
- match opt_c {
- Some(_) => {
- if opt_c != c_iter.next() {
- return false;
+fn compare_pstr_to_string<'a>(
+ heap_pstr_iter: &mut HeapPStrIter<'a>,
+ s: &String,
+) -> Option<usize> {
+ let mut s_offset = 0;
+
+ while let Some(iteratee) = heap_pstr_iter.next() {
+ match iteratee {
+ PStrIteratee::Char(c1) => {
+ if let Some(c2) = s[s_offset ..].chars().next() {
+ if c1 != c2 {
+ return None;
+ } else {
+ s_offset += c1.len_utf8();
+ }
+ } else {
+ return None;
}
}
- None => {
- return c_iter.next().is_none();
+ PStrIteratee::PStrSegment(h, n) => {
+ match heap_pstr_iter.machine_st.heap[h] {
+ HeapCellValue::PartialString(ref pstr, _) => {
+ let t = pstr.as_str_from(n);
+
+ if s[s_offset ..].starts_with(t) {
+ s_offset += t.len();
+ } else if t.starts_with(&s[s_offset ..]) {
+ heap_pstr_iter.focus =
+ Addr::PStrLocation(h, n + s[s_offset ..].len());
+
+ s_offset += s[s_offset ..].len();
+ return Some(s_offset);
+ } else {
+ return None;
+ }
+ }
+ _ => {
+ unreachable!()
+ }
+ }
}
}
}
- false
+ Some(s_offset)
}
pub struct Ball {
HeapPtr::HeapCell(ref mut h) => {
*h += rhs;
}
- &mut HeapPtr::PStrChar(h, ref mut n)
- | &mut HeapPtr::PStrLocation(h, ref mut n) => {
+ &mut HeapPtr::PStrChar(h, ref mut n) |
+ &mut HeapPtr::PStrLocation(h, ref mut n) => {
match &self.heap[h] {
HeapCellValue::PartialString(ref pstr, _) => {
for c in pstr.range_from(*n ..).take(rhs) {
self.trail.truncate(self.tr);
}
+ pub(super)
+ fn match_partial_string(&mut self, addr: Addr, string: &String, has_tail: bool) {
+ let mut heap_pstr_iter = self.heap_pstr_iter(addr);
+
+ match compare_pstr_to_string(&mut heap_pstr_iter, string) {
+ Some(prefix_len) if prefix_len == string.len() => {
+ let focus = heap_pstr_iter.focus();
+
+ match focus {
+ Addr::PStrLocation(h, n) => {
+ if has_tail {
+ self.s = HeapPtr::PStrLocation(h, n);
+ self.mode = MachineMode::Read;
+ } else {
+ self.fail = true;
+ }
+ }
+ addr => {
+ if has_tail {
+ let h = self.heap.h();
+
+ self.heap.push(HeapCellValue::Addr(Addr::HeapCell(h)));
+ self.bind(Ref::HeapCell(h), addr);
+
+ self.s = HeapPtr::HeapCell(h);
+ self.mode = MachineMode::Read;
+ } else {
+ if let Some(var) = addr.as_var() {
+ self.bind(var, Addr::EmptyList);
+ } else {
+ self.fail = true;
+ }
+ }
+ }
+ }
+ }
+ Some(prefix_len) => {
+ match heap_pstr_iter.focus() {
+ addr @ Addr::AttrVar(_) |
+ addr @ Addr::StackCell(..) |
+ addr @ Addr::HeapCell(_) => {
+ let h = self.heap.h();
+
+ let pstr_addr =
+ if has_tail {
+ self.s = HeapPtr::HeapCell(h+1);
+ self.mode = MachineMode::Read;
+
+ self.heap.allocate_pstr(&string[prefix_len ..])
+ } else {
+ self.heap.put_complete_string(&string[prefix_len ..])
+ };
+
+ self.bind(addr.as_var().unwrap(), pstr_addr);
+ }
+ Addr::Lis(l) if !self.flags.double_quotes.is_atom() => {
+ let h = self.heap.h();
+
+ let pstr_addr =
+ if has_tail {
+ self.s = HeapPtr::HeapCell(h+1);
+ self.mode = MachineMode::Read;
+
+ self.heap.allocate_pstr(&string[prefix_len ..])
+ } else {
+ self.heap.put_complete_string(&string[prefix_len ..])
+ };
+
+ self.unify(Addr::Lis(l), pstr_addr);
+ }
+ _ => {
+ self.fail = true;
+ }
+ }
+ }
+ None => {
+ self.fail = true;
+ }
+ }
+ }
+
pub(super)
fn write_constant_to_var(&mut self, addr: Addr, c: &Constant) {
match self.store(self.deref(addr)) {
Addr::Con(c1) => {
- self.fail = match &self.heap[c1] {
+ match &self.heap[c1] {
HeapCellValue::Atom(ref n1, _) => {
- match c {
+ self.fail = match c {
Constant::Atom(ref n2, _) => {
n1 != n2
}
_ => {
true
}
- }
+ };
}
HeapCellValue::Integer(ref n1) => {
- match c {
+ self.fail = match c {
Constant::Fixnum(n2) => {
n1.to_isize() != Some(*n2)
}
_ => {
true
}
- }
+ };
}
HeapCellValue::Rational(ref r1) => {
- if let Constant::Rational(ref r2) = c {
+ self.fail = if let Constant::Rational(ref r2) = c {
r1 != r2
} else {
true
}
HeapCellValue::PartialString(..) => {
if let Constant::String(ref s2) = c {
- let iter = self.heap_pstr_iter(Addr::PStrLocation(c1, 0));
- !compare_pstr(iter, s2.chars())
+ self.match_partial_string(
+ Addr::PStrLocation(c1, 0),
+ &s2,
+ false,
+ );
} else {
- true
+ self.fail = true;
}
}
_ => {
self.unify(Addr::Lis(l), addr);
}
Addr::PStrLocation(h, n) => {
- self.fail = if let Constant::String(ref s2) = c {
- let iter = self.heap_pstr_iter(Addr::PStrLocation(h, n));
- !compare_pstr(iter, s2.chars())
+ if let Constant::String(ref s2) = c {
+ self.match_partial_string(
+ Addr::PStrLocation(h, n),
+ &s2,
+ false,
+ )
} else {
- true
+ self.fail = true;
};
}
Addr::Stream(_) => {
self.s = HeapPtr::PStrChar(h, n);
self.mode = MachineMode::Read;
}
- addr @ Addr::AttrVar(_)
- | addr @ Addr::StackCell(..)
- | addr @ Addr::HeapCell(_) => {
+ addr @ Addr::AttrVar(_) |
+ addr @ Addr::StackCell(..) |
+ addr @ Addr::HeapCell(_) => {
let h = self.heap.h();
self.heap.push(HeapCellValue::Addr(Addr::Lis(h + 1)));
self.s = HeapPtr::HeapCell(a);
self.mode = MachineMode::Read;
}
- _ => self.fail = true,
+ _ => {
+ self.fail = true;
+ }
};
}
+ &FactInstruction::GetPartialString(_, ref string, reg, has_tail) => {
+ let addr = self.store(self.deref(self[reg]));
+ self.match_partial_string(addr, string, has_tail);
+ }
&FactInstruction::GetStructure(ref ct, arity, reg) => {
let addr = self.deref(self[reg]);
let h = self.heap.h();
self.heap.push(HeapCellValue::Addr(Addr::Str(h + 1)));
- self.heap
- .push(HeapCellValue::NamedStr(arity, ct.name(), ct.spec()));
+ self.heap.push(HeapCellValue::NamedStr(arity, ct.name(), ct.spec()));
self.bind(addr.as_var().unwrap(), Addr::HeapCell(h));
self.mode = MachineMode::Write;
}
- _ => self.fail = true,
+ _ => {
+ self.fail = true;
+ }
};
}
&FactInstruction::GetVariable(norm, arg) => {
match self.mode {
MachineMode::Read => {
let addr = self.s.read(&self.heap);
+
self.write_constant_to_var(addr, c);
+ self.increment_s_ptr(1);
}
MachineMode::Write => {
let addr = self.heap.put_constant(c.clone());
}
}
};
-
- self.increment_s_ptr(1);
}
&FactInstruction::UnifyVariable(reg) => {
match self.mode {
- MachineMode::Read => self[reg] = self.s.read(&self.heap),
+ MachineMode::Read => {
+ self[reg] = self.s.read(&self.heap);
+ self.increment_s_ptr(1);
+ }
MachineMode::Write => {
let h = self.heap.h();
self[reg] = Addr::HeapCell(h);
}
};
-
- self.increment_s_ptr(1);
}
&FactInstruction::UnifyLocalValue(reg) => {
match self.mode {
MachineMode::Read => {
let reg_addr = self[reg];
+
self.unify(reg_addr, self.s.read(&self.heap));
+ self.increment_s_ptr(1);
}
MachineMode::Write => {
let addr = self.deref(self[reg]);
self.bind(Ref::HeapCell(h), addr);
}
};
-
- self.increment_s_ptr(1);
}
&FactInstruction::UnifyValue(reg) => {
match self.mode {
MachineMode::Read => {
let reg_addr = self[reg];
+
self.unify(reg_addr, self.s.read(&self.heap));
+ self.increment_s_ptr(1);
}
MachineMode::Write => {
let heap_val = self.store(self[reg]);
self.heap.push(HeapCellValue::Addr(heap_val));
}
};
-
- self.increment_s_ptr(1);
}
&FactInstruction::UnifyVoid(n) => {
match self.mode {
- MachineMode::Read => self.increment_s_ptr(n),
+ MachineMode::Read => {
+ self.increment_s_ptr(n);
+ }
MachineMode::Write => {
let h = self.heap.h();
&QueryInstruction::PutList(_, reg) => {
self[reg] = Addr::Lis(self.heap.h());
}
+ &QueryInstruction::PutPartialString(_, ref string, reg, has_tail) => {
+ let pstr_addr =
+ if has_tail {
+ let pstr_addr = self.heap.allocate_pstr(&string);
+ self.heap.pop(); // the tail will be added by the next instruction.
+ pstr_addr
+ } else {
+ self.heap.put_complete_string(&string)
+ };
+
+ self[reg] = pstr_addr;
+ }
&QueryInstruction::PutStructure(ref ct, arity, reg) => {
let h = self.heap.h();
&QueryInstruction::SetVoid(n) => {
let h = self.heap.h();
- for i in h..h + n {
+ for i in h .. h + n {
self.heap.push(HeapCellValue::Addr(Addr::HeapCell(i)));
}
}
current_output_stream: &mut Stream,
) {
match instr {
- &Line::Arithmetic(ref arith_instr) => self.execute_arith_instr(arith_instr),
+ &Line::Arithmetic(ref arith_instr) => {
+ self.execute_arith_instr(arith_instr)
+ }
&Line::Choice(ref choice_instr) => {
self.execute_choice_instr(choice_instr, &mut policies.call_policy)
}
&Line::Cut(ref cut_instr) => {
self.execute_cut_instr(cut_instr, &mut policies.cut_policy)
}
- &Line::Control(ref control_instr) => self.execute_ctrl_instr(
- indices,
- code_repo,
- &mut policies.call_policy,
- &mut policies.cut_policy,
- current_input_stream,
- current_output_stream,
- control_instr,
- ),
+ &Line::Control(ref control_instr) => {
+ self.execute_ctrl_instr(
+ indices,
+ code_repo,
+ &mut policies.call_policy,
+ &mut policies.cut_policy,
+ current_input_stream,
+ current_output_stream,
+ control_instr,
+ )
+ }
&Line::Fact(ref fact_instr) => {
self.execute_fact_instr(&fact_instr);
self.p += 1;
}
- &Line::Indexing(ref indexing_instr) => self.execute_indexing_instr(&indexing_instr),
+ &Line::Indexing(ref indexing_instr) => {
+ self.execute_indexing_instr(&indexing_instr)
+ }
&Line::IndexedChoice(ref choice_instr) => {
self.execute_indexed_choice_instr(choice_instr, &mut policies.call_policy)
}
pub(super)
fn clone_from_offset(&self, n: usize) -> Self {
- let len = if self.len > n { self.len - n } else { 0 };
+ let len =
+ if self.len - '\u{0}'.len_utf8() > n {
+ self.len - n - '\u{0}'.len_utf8()
+ } else {
+ 0
+ };
let mut pstr = PartialString {
buf: ptr::null_mut(),
ptr::read((self.buf as usize + end_n) as *const u8) == 0u8
}
}
+
+ #[inline]
+ pub fn as_str_from(&self, n: usize) -> &str {
+ unsafe {
+ let slice = slice::from_raw_parts(
+ self.buf,
+ self.len - '\u{0}'.len_utf8(),
+ );
+
+ let s = str::from_utf8(slice).unwrap();
+
+ &s[n ..]
+ }
+ }
}
Ok(TopLevel::Fact(self.setup_fact(term, true)?, self.line_num, self.col_num))
}
}
- term =>
- Ok(TopLevel::Fact(self.setup_fact(term, true)?, self.line_num, self.col_num)),
+ term => {
+ Ok(TopLevel::Fact(self.setup_fact(term, true)?, self.line_num, self.col_num))
+ }
}
}
fn absorb(&mut self, other: RelationWorker) {
self.queue.extend(other.queue.into_iter());
- self.dynamic_clauses
- .extend(other.dynamic_clauses.into_iter());
+ self.dynamic_clauses.extend(other.dynamic_clauses.into_iter());
}
}
(atom($e:expr), $arity:expr, $aux_lens:expr, $addendum: ident) => (
HeapCellValue::Atom(clause_name!($e), None)
);
+ (string($h:expr, $e:expr), $arity:expr, $aux_lens:expr, $addendum: ident) => ({
+ let len: usize = $aux_lens.iter().sum();
+ let h = len + $arity + 1 + $addendum.h() + $h;
+
+ $addendum.put_complete_string(&$e);
+
+ HeapCellValue::Addr(Addr::PStrLocation(h, 0))
+ });
+ (boolean($e:expr), $arity:expr, $aux_lens:expr, $addendum: ident) => ({
+ if $e {
+ functor_term!(atom("true"), $arity, $aux_lens, $addendum)
+ } else {
+ functor_term!(atom("false"), $arity, $aux_lens, $addendum)
+ }
+ });
($e:expr, $arity:expr, $aux_lens:expr, $addendum:ident) => (
$e
);
let len: usize = $aux_lens.iter().sum();
let h = len + $arity + 1 + $addendum.h() + $over_h;
- $addendum.put_constant(Constant::String(s.clone()));
+ $addendum.put_complete_string(&s);
HeapCellValue::Addr(Addr::PStrLocation(h, 0))
}
use crate::prolog::forms::*;
use crate::prolog::iterators::*;
-use crate::prolog::machine::heap::Heap;
use crate::prolog::machine::machine_indices::*;
use crate::prolog::machine::machine_state::MachineState;
use crate::prolog::machine::streams::Stream;
type SubtermDeque = VecDeque<(usize, usize)>;
-impl<'a> TermRef<'a> {
- fn as_addr(&self, heap: &mut Heap, h: usize) -> Addr {
- match self {
- &TermRef::AnonVar(_) | &TermRef::Var(..) => {
- Addr::HeapCell(h)
- }
- &TermRef::Cons(..) => {
- Addr::HeapCell(h)
- }
- &TermRef::Constant(_, _, c) => {
- heap.put_constant(c.clone())
- }
- &TermRef::Clause(..) => {
- Addr::Str(h)
- }
- }
- }
-}
-
pub type PrologStream = ParsingStream<Stream>;
pub mod readline {
result => {
result
}
-
}
}
}
}
}
-fn push_stub_addr(machine_st: &mut MachineState) {
- let h = machine_st.heap.h();
- machine_st.heap.push(HeapCellValue::Addr(Addr::HeapCell(h)));
+#[inline]
+pub(crate)
+fn write_term_to_heap(term: &Term, machine_st: &mut MachineState) -> TermWriteResult {
+ let term_writer = TermWriter::new(machine_st);
+ term_writer.write_term_to_heap(term)
}
-fn modify_head_of_queue(
- machine_st: &mut MachineState,
- queue: &mut SubtermDeque,
- term: TermRef,
- h: usize,
-) {
- if let Some((arity, site_h)) = queue.pop_front() {
- machine_st.heap[site_h] = HeapCellValue::Addr(term.as_addr(&mut machine_st.heap, h));
-
- if arity > 1 {
- queue.push_front((arity - 1, site_h + 1));
- }
- }
+struct TermWriter<'a> {
+ machine_st: &'a mut MachineState,
+ queue: SubtermDeque,
+ var_dict: HeapVarDict,
}
pub struct TermWriteResult {
pub(crate) var_dict: HeapVarDict,
}
-pub(crate)
-fn write_term_to_heap(term: &Term, machine_st: &mut MachineState) -> TermWriteResult {
- let heap_loc = machine_st.heap.h();
+impl<'a> TermWriter<'a> {
+ #[inline]
+ fn new(machine_st: &'a mut MachineState) -> Self {
+ TermWriter {
+ machine_st,
+ queue: SubtermDeque::new(),
+ var_dict: HeapVarDict::new(),
+ }
+ }
- let mut queue = SubtermDeque::new();
- let mut var_dict = HeapVarDict::new();
+ #[inline]
+ fn modify_head_of_queue(&mut self, term: &TermRef<'a>, h: usize) {
+ if let Some((arity, site_h)) = self.queue.pop_front() {
+ self.machine_st.heap[site_h] =
+ HeapCellValue::Addr(self.term_as_addr(term, h));
- for term in breadth_first_iter(term, true) {
- let h = machine_st.heap.h();
+ if arity > 1 {
+ self.queue.push_front((arity - 1, site_h + 1));
+ }
+ }
+ }
- match &term {
- &TermRef::Cons(lvl, ..) => {
- queue.push_back((2, h + 1));
- machine_st.heap.push(HeapCellValue::Addr(Addr::Lis(h + 1)));
+ #[inline]
+ fn push_stub_addr(&mut self) {
+ let h = self.machine_st.heap.h();
+ self.machine_st.heap.push(HeapCellValue::Addr(Addr::HeapCell(h)));
+ }
- push_stub_addr(machine_st);
- push_stub_addr(machine_st);
+ fn term_as_addr(&mut self, term: &TermRef<'a>, h: usize) -> Addr {
+ match term {
+ &TermRef::AnonVar(_) | &TermRef::Var(..) => {
+ Addr::HeapCell(h)
+ }
+ &TermRef::Cons(..) => {
+ Addr::HeapCell(h)
+ }
+ &TermRef::Constant(_, _, c) => {
+ self.machine_st.heap.put_constant(c.clone())
+ }
+ &TermRef::Clause(..) => {
+ Addr::Str(h)
+ }
+ &TermRef::PartialString(..) => {//_, _, ref pstr, tail) => {
+ Addr::PStrLocation(h, 0)
+ /*
+ match tail {
+ Term::AnonVar => {
+ let h = self.machine_st.heap.h();
+ self.machine_st.heap.allocate_pstr(pstr);
+
+ Addr::PStrLocation(h, 0)
+ }
+ Term::Constant(_, Constant::EmptyList) => {
+ self.machine_st.heap.put_complete_string(pstr)
+ }
+ Term::Var(_, ref var) => {
+ let h = self.machine_st.heap.h();
- if let Level::Root = lvl {
- continue;
+ self.machine_st.heap.allocate_pstr(pstr);
+ let tail_h = self.machine_st.heap.h() - 1;
+
+ if let Some(addr) = self.var_dict.get(var) {
+ self.machine_st.heap[tail_h] = HeapCellValue::Addr(*addr);
+ } else {
+ self.var_dict.insert(var.clone(), Addr::HeapCell(tail_h));
+ }
+
+ Addr::PStrLocation(h, 0)
+ }
+ _ => {
+ unreachable!()
+ }
}
+ */
}
- &TermRef::Clause(lvl, _, ref ct, subterms) => {
- queue.push_back((subterms.len(), h + 1));
- let named = HeapCellValue::NamedStr(subterms.len(), ct.name(), ct.spec());
+ }
+ }
- machine_st.heap.push(named);
+ fn write_term_to_heap(mut self, term: &'a Term) -> TermWriteResult {
+ let heap_loc = self.machine_st.heap.h();
- for _ in 0..subterms.len() {
- push_stub_addr(machine_st);
- }
+ for term in breadth_first_iter(term, true) {
+ let h = self.machine_st.heap.h();
- if let Level::Root = lvl {
- continue;
+ match &term {
+ &TermRef::Cons(lvl, ..) => {
+ self.queue.push_back((2, h + 1));
+ self.machine_st.heap.push(HeapCellValue::Addr(Addr::Lis(h + 1)));
+
+ self.push_stub_addr();
+ self.push_stub_addr();
+
+ if let Level::Root = lvl {
+ continue;
+ }
}
- }
- &TermRef::AnonVar(Level::Root) | &TermRef::Constant(Level::Root, ..)
- | &TermRef::Var(Level::Root, ..) => {
- let addr = term.as_addr(&mut machine_st.heap, h);
+ &TermRef::Clause(lvl, _, ref ct, subterms) => {
+ self.queue.push_back((subterms.len(), h + 1));
+ let named = HeapCellValue::NamedStr(subterms.len(), ct.name(), ct.spec());
+
+ self.machine_st.heap.push(named);
+
+ for _ in 0..subterms.len() {
+ self.push_stub_addr();
+ }
- if !addr.is_heap_bound() {
- machine_st.heap.push(HeapCellValue::Addr(addr));
+ if let Level::Root = lvl {
+ continue;
+ }
}
- }
- &TermRef::AnonVar(_) => {
- if let Some((arity, site_h)) = queue.pop_front() {
- if arity > 1 {
- queue.push_front((arity - 1, site_h + 1));
+ &TermRef::AnonVar(Level::Root) | &TermRef::Constant(Level::Root, ..) |
+ &TermRef::Var(Level::Root, ..) => {
+ let addr = self.term_as_addr(&term, h);
+
+ if !addr.is_heap_bound() {
+ self.machine_st.heap.push(HeapCellValue::Addr(addr));
}
}
+ &TermRef::AnonVar(_) => {
+ if let Some((arity, site_h)) = self.queue.pop_front() {
+ if arity > 1 {
+ self.queue.push_front((arity - 1, site_h + 1));
+ }
+ }
- continue;
- }
- &TermRef::Var(_, _, ref var) => {
- if let Some((arity, site_h)) = queue.pop_front() {
- if let Some(addr) = var_dict.get(var).cloned() {
- machine_st.heap[site_h] = HeapCellValue::Addr(addr);
+ continue;
+ }
+ &TermRef::PartialString(lvl, _, ref pstr, tail) => {
+ if tail.is_some() {
+ self.machine_st.heap.allocate_pstr(&pstr);
} else {
- var_dict.insert(var.clone(), Addr::HeapCell(site_h));
+ self.machine_st.heap.put_complete_string(&pstr);
}
- if arity > 1 {
- queue.push_front((arity - 1, site_h + 1));
+ if let Level::Root = lvl {
+ } else if tail.is_some() {
+ let h = self.machine_st.heap.h();
+ self.queue.push_back((1, h - 1));
}
}
+ &TermRef::Var(_, _, ref var) => {
+ if let Some((arity, site_h)) = self.queue.pop_front() {
+ if let Some(addr) = self.var_dict.get(var).cloned() {
+ self.machine_st.heap[site_h] = HeapCellValue::Addr(addr);
+ } else {
+ self.var_dict.insert(var.clone(), Addr::HeapCell(site_h));
+ }
- continue;
- }
- _ => {}
- };
+ if arity > 1 {
+ self.queue.push_front((arity - 1, site_h + 1));
+ }
+ }
- modify_head_of_queue(machine_st, &mut queue, term, h);
- }
+ continue;
+ }
+ _ => {
+ }
+ };
+
+ self.modify_head_of_queue(&term, h);
+ }
- TermWriteResult { heap_loc, var_dict }
+ TermWriteResult { heap_loc, var_dict: self.var_dict }
+ }
}
fn to_void(_: usize) -> Self;
fn is_void_instr(&self) -> bool;
+ fn to_pstr(lvl: Level, string: String, r: RegType, has_tail: bool) -> Self;
+
fn incr_void_instr(&mut self);
fn constant_subterm(_: Constant) -> Self;
}
}
+ fn to_pstr(lvl: Level, string: String, r: RegType, has_tail: bool) -> Self {
+ FactInstruction::GetPartialString(lvl, string, r, has_tail)
+ }
+
fn incr_void_instr(&mut self) {
match self {
&mut FactInstruction::UnifyVoid(ref mut incr) => *incr += 1,
QueryInstruction::PutList(lvl, reg)
}
+ fn to_pstr(lvl: Level, string: String, r: RegType, has_tail: bool) -> Self {
+ QueryInstruction::PutPartialString(lvl, string, r, has_tail)
+ }
+
fn to_void(subterms: usize) -> Self {
QueryInstruction::SetVoid(subterms)
}
match self {
REPLCodePtr::CompileBatch =>
write!(f, "REPLCodePtr::CompileBatch"),
- REPLCodePtr::UseModule =>
- write!(f, "REPLCodePtr::UseModule"),
- REPLCodePtr::UseQualifiedModule =>
- write!(f, "REPLCodePtr::UseQualifiedModule"),
- REPLCodePtr::UseModuleFromFile =>
- write!(f, "REPLCodePtr::UseModuleFromFile"),
- REPLCodePtr::UseQualifiedModuleFromFile =>
- write!(f, "REPLCodePtr::UseQualifiedModuleFromFile")
+ REPLCodePtr::UseModule =>
+ write!(f, "REPLCodePtr::UseModule"),
+ REPLCodePtr::UseQualifiedModule =>
+ write!(f, "REPLCodePtr::UseQualifiedModule"),
+ REPLCodePtr::UseModuleFromFile =>
+ write!(f, "REPLCodePtr::UseModuleFromFile"),
+ REPLCodePtr::UseQualifiedModuleFromFile =>
+ write!(f, "REPLCodePtr::UseQualifiedModuleFromFile")
}
}
}
&FactInstruction::GetConstant(lvl, ref constant, ref r) => {
write!(f, "get_constant {}, {}{}", constant, lvl, r.reg_num())
}
- &FactInstruction::GetList(lvl, ref r) => write!(f, "get_list {}{}", lvl, r.reg_num()),
+ &FactInstruction::GetList(lvl, ref r) => {
+ write!(f, "get_list {}{}", lvl, r.reg_num())
+ }
+ &FactInstruction::GetPartialString(lvl, ref s, r, has_tail) => {
+ write!(f, "get_partial_string({}, {}, {}, {})",
+ lvl, s, r, has_tail)
+ }
&FactInstruction::GetStructure(ref ct, ref arity, ref r) => {
write!(f, "get_structure {}/{}, {}", ct.name(), arity, r)
}
&QueryInstruction::PutConstant(lvl, ref constant, ref r) => {
write!(f, "put_constant {}, {}{}", constant, lvl, r.reg_num())
}
- &QueryInstruction::PutList(lvl, ref r) => write!(f, "put_list {}{}", lvl, r.reg_num()),
+ &QueryInstruction::PutList(lvl, ref r) => {
+ write!(f, "put_list {}{}", lvl, r.reg_num())
+ }
+ &QueryInstruction::PutPartialString(lvl, ref s, r, has_tail) => {
+ write!(f, "put_partial_string({}, {}, {}, {})",
+ lvl, s, r, has_tail)
+ }
&QueryInstruction::PutStructure(ref ct, ref arity, ref r) => {
write!(f, "put_structure {}/{}, {}", ct.name(), arity, r)
}
write!(f, "{}/{}", name.as_str(), arity)
}
&HeapCellValue::PartialString(ref pstr, has_tail) => {
- write!(f, "pstr ( buf: 0x{:x}, has_tail({}) )",
- (pstr as *const _) as usize,
- has_tail)
+ write!(
+ f,
+ "pstr ( buf: \"{}\", has_tail({}) )",
+ pstr.as_str_from(0),
+ has_tail,
+ )
}
&HeapCellValue::Stream(ref stream) => {
write!(f, "$stream({})", stream.as_ptr() as usize)