fix printer
This commit is contained in:
@@ -10,7 +10,7 @@ license = "BSD-3-Clause"
|
|||||||
downcast = "0.9.1"
|
downcast = "0.9.1"
|
||||||
num = "0.2"
|
num = "0.2"
|
||||||
ordered-float = "0.5.0"
|
ordered-float = "0.5.0"
|
||||||
prolog_parser = { version = "0.7.22", path = "../prolog_parser" }
|
prolog_parser = "0.7.22"
|
||||||
|
|
||||||
[dependencies.termion]
|
[dependencies.termion]
|
||||||
version = "1.4.0"
|
version = "1.4.0"
|
||||||
@@ -9,6 +9,7 @@ use prolog::ordered_float::OrderedFloat;
|
|||||||
use std::cell::Cell;
|
use std::cell::Cell;
|
||||||
use std::collections::{HashMap, HashSet};
|
use std::collections::{HashMap, HashSet};
|
||||||
use std::iter::once;
|
use std::iter::once;
|
||||||
|
use std::ops::{Range, RangeFrom};
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
/* contains the location, name, precision and Specifier of the parent op. */
|
/* contains the location, name, precision and Specifier of the parent op. */
|
||||||
@@ -54,7 +55,6 @@ pub enum TokenOrRedirect {
|
|||||||
OpenList(Rc<Cell<bool>>),
|
OpenList(Rc<Cell<bool>>),
|
||||||
CloseList(Rc<Cell<bool>>),
|
CloseList(Rc<Cell<bool>>),
|
||||||
HeadTailSeparator,
|
HeadTailSeparator,
|
||||||
Space
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait HCValueOutputter {
|
pub trait HCValueOutputter {
|
||||||
@@ -64,11 +64,13 @@ pub trait HCValueOutputter {
|
|||||||
fn push_char(&mut self, char);
|
fn push_char(&mut self, char);
|
||||||
fn append(&mut self, &str);
|
fn append(&mut self, &str);
|
||||||
fn begin_new_var(&mut self);
|
fn begin_new_var(&mut self);
|
||||||
fn insert_from_end(&mut self, usize, char);
|
fn insert(&mut self, usize, char);
|
||||||
fn result(self) -> Self::Output;
|
fn result(self) -> Self::Output;
|
||||||
fn ends_with(&self, &str) -> bool;
|
fn ends_with(&self, &str) -> bool;
|
||||||
fn len(&self) -> usize;
|
fn len(&self) -> usize;
|
||||||
fn truncate(&mut self, usize);
|
fn truncate(&mut self, usize);
|
||||||
|
fn range(&self, Range<usize>) -> &str;
|
||||||
|
fn range_from(&self, RangeFrom<usize>) -> &str;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct PrinterOutputter {
|
pub struct PrinterOutputter {
|
||||||
@@ -96,9 +98,8 @@ impl HCValueOutputter for PrinterOutputter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn insert_from_end(&mut self, idx: usize, c: char) {
|
fn insert(&mut self, idx: usize, c: char) {
|
||||||
let len = self.contents.len();
|
self.contents.insert(idx, c);
|
||||||
self.contents.insert(len - idx, c);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn result(self) -> Self::Output {
|
fn result(self) -> Self::Output {
|
||||||
@@ -116,6 +117,14 @@ impl HCValueOutputter for PrinterOutputter {
|
|||||||
fn truncate(&mut self, len: usize) {
|
fn truncate(&mut self, len: usize) {
|
||||||
self.contents.truncate(len);
|
self.contents.truncate(len);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn range(&self, index: Range<usize>) -> &str {
|
||||||
|
&self.contents.as_str()[index]
|
||||||
|
}
|
||||||
|
|
||||||
|
fn range_from(&self, index: RangeFrom<usize>) -> &str {
|
||||||
|
&self.contents.as_str()[index]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
@@ -158,34 +167,29 @@ pub struct HCPrinter<'a, Outputter> {
|
|||||||
state_stack: Vec<TokenOrRedirect>,
|
state_stack: Vec<TokenOrRedirect>,
|
||||||
heap_locs: ReverseHeapVarDict,
|
heap_locs: ReverseHeapVarDict,
|
||||||
printed_vars: HashSet<Addr>,
|
printed_vars: HashSet<Addr>,
|
||||||
|
last_item_idx: usize,
|
||||||
pub(crate) numbervars: bool,
|
pub(crate) numbervars: bool,
|
||||||
pub(crate) quoted: bool,
|
pub(crate) quoted: bool,
|
||||||
pub(crate) ignore_ops: bool
|
pub(crate) ignore_ops: bool
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! push_space_if_amb {
|
macro_rules! push_space_if_amb {
|
||||||
($self:expr, $atom:expr, $op:expr, $action:block) => (
|
($self:expr, $atom:expr, $action:block) => (
|
||||||
match $self.ambiguity_check($atom, $op) {
|
if $self.ambiguity_check($atom) {
|
||||||
Some(DirectedOp::Left(lop, (_, spec))) =>
|
if !$self.outputter.range(0 .. $self.last_item_idx).ends_with(" ") {
|
||||||
if is_infix!(spec) {
|
$self.outputter.insert($self.last_item_idx, ' ');
|
||||||
$self.outputter.insert_from_end(lop.as_str().len(), ' ');
|
}
|
||||||
$self.outputter.push_char(' ');
|
|
||||||
$action;
|
$self.outputter.push_char(' ');
|
||||||
} else {
|
$action;
|
||||||
$self.outputter.push_char(' ');
|
} else {
|
||||||
$action;
|
$action;
|
||||||
},
|
}
|
||||||
Some(DirectedOp::Right(..)) => {
|
|
||||||
$action;
|
|
||||||
$self.outputter.push_char(' ');
|
|
||||||
},
|
|
||||||
None => $action
|
|
||||||
};
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn continues_with_append(atom: &str, op: &str) -> bool {
|
fn continues_with_append(atom: &str, op: &str) -> bool {
|
||||||
match atom.chars().next() {
|
match atom.chars().last() {
|
||||||
Some(ac) => op.chars().next().map(|oc| {
|
Some(ac) => op.chars().next().map(|oc| {
|
||||||
if alpha_char!(ac) {
|
if alpha_char!(ac) {
|
||||||
alpha_numeric_char!(oc)
|
alpha_numeric_char!(oc)
|
||||||
@@ -269,6 +273,7 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter>
|
|||||||
state_stack: vec![],
|
state_stack: vec![],
|
||||||
heap_locs: ReverseHeapVarDict::new(),
|
heap_locs: ReverseHeapVarDict::new(),
|
||||||
printed_vars: HashSet::new(),
|
printed_vars: HashSet::new(),
|
||||||
|
last_item_idx: 0,
|
||||||
numbervars: false,
|
numbervars: false,
|
||||||
quoted: false,
|
quoted: false,
|
||||||
ignore_ops: false }
|
ignore_ops: false }
|
||||||
@@ -291,28 +296,11 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// return op itself if there is an ambiguity to indicate the direction the op
|
#[inline]
|
||||||
// lies, None otherwise.
|
fn ambiguity_check(&self, atom: &str) -> bool
|
||||||
fn ambiguity_check(&self, atom: &str, op: &Option<DirectedOp>) -> Option<DirectedOp>
|
|
||||||
{
|
{
|
||||||
match op {
|
let tail = self.outputter.range_from(self.last_item_idx ..);
|
||||||
&Some(DirectedOp::Left(ref lop, (priority, spec))) if is_infix!(spec) =>
|
continues_with_append(tail, atom)
|
||||||
if self.outputter.ends_with(&format!(" {}", lop.as_str())) {
|
|
||||||
Some(DirectedOp::Left(lop.clone(), (priority, spec)))
|
|
||||||
} else if continues_with_append(lop.as_str(), atom) {
|
|
||||||
Some(DirectedOp::Left(lop.clone(), (priority, spec)))
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
},
|
|
||||||
&Some(DirectedOp::Left(ref lop, spec))
|
|
||||||
if continues_with_append(lop.as_str(), atom) =>
|
|
||||||
Some(DirectedOp::Left(lop.clone(), spec)),
|
|
||||||
&Some(DirectedOp::Right(ref rop, spec))
|
|
||||||
if continues_with_append(atom, rop.as_str()) =>
|
|
||||||
Some(DirectedOp::Right(rop.clone(), spec)),
|
|
||||||
_ =>
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn enqueue_op(&mut self, ct: ClauseType, spec: (usize, Specifier)) {
|
fn enqueue_op(&mut self, ct: ClauseType, spec: (usize, Specifier)) {
|
||||||
@@ -371,6 +359,18 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter>
|
|||||||
self.format_struct(arity, ct.name());
|
self.format_struct(arity, ct.name());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn push_char(&mut self, c: char) {
|
||||||
|
self.outputter.push_char(c);
|
||||||
|
self.last_item_idx = self.outputter.len();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn append_str(&mut self, s: &str) {
|
||||||
|
self.last_item_idx = self.outputter.len();
|
||||||
|
self.outputter.append(s);
|
||||||
|
}
|
||||||
|
|
||||||
fn offset_as_string(&self, addr: Addr) -> Option<String> {
|
fn offset_as_string(&self, addr: Addr) -> Option<String> {
|
||||||
match addr {
|
match addr {
|
||||||
Addr::HeapCell(h) | Addr::Lis(h) | Addr::Str(h) =>
|
Addr::HeapCell(h) | Addr::Lis(h) | Addr::Str(h) =>
|
||||||
@@ -381,8 +381,7 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_for_seen(&mut self, iter: &mut HCPreOrderIterator, op: &Option<DirectedOp>)
|
fn check_for_seen(&mut self, iter: &mut HCPreOrderIterator) -> Option<HeapCellValue>
|
||||||
-> Option<HeapCellValue>
|
|
||||||
{
|
{
|
||||||
iter.stack().last().cloned().and_then(|addr| {
|
iter.stack().last().cloned().and_then(|addr| {
|
||||||
let addr = self.machine_st.store(self.machine_st.deref(addr));
|
let addr = self.machine_st.store(self.machine_st.deref(addr));
|
||||||
@@ -393,8 +392,8 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter>
|
|||||||
return iter.next();
|
return iter.next();
|
||||||
} else {
|
} else {
|
||||||
iter.stack().pop();
|
iter.stack().pop();
|
||||||
push_space_if_amb!(self, &var, op, {
|
push_space_if_amb!(self, &var, {
|
||||||
self.outputter.append(&var);
|
self.append_str(&var);
|
||||||
});
|
});
|
||||||
|
|
||||||
return None;
|
return None;
|
||||||
@@ -404,8 +403,8 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter>
|
|||||||
iter.stack().pop();
|
iter.stack().pop();
|
||||||
|
|
||||||
if let Some(offset_str) = self.offset_as_string(addr) {
|
if let Some(offset_str) = self.offset_as_string(addr) {
|
||||||
push_space_if_amb!(self, &offset_str, op, {
|
push_space_if_amb!(self, &offset_str, {
|
||||||
self.outputter.append(offset_str.as_str());
|
self.append_str(offset_str.as_str());
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -428,13 +427,13 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter>
|
|||||||
|
|
||||||
fn print_atom(&mut self, atom: &ClauseName, spec: Option<(usize, Specifier)>) {
|
fn print_atom(&mut self, atom: &ClauseName, spec: Option<(usize, Specifier)>) {
|
||||||
match atom.as_str() {
|
match atom.as_str() {
|
||||||
"" => self.outputter.append("''"),
|
"" => self.append_str("''"),
|
||||||
";" | "!" => self.outputter.append(atom.as_str()),
|
";" | "!" => self.append_str(atom.as_str()),
|
||||||
s => if spec.is_some() || !self.quoted || non_quoted_token(s.chars()) {
|
s => if spec.is_some() || !self.quoted || non_quoted_token(s.chars()) {
|
||||||
self.outputter.append(atom.as_str())
|
self.append_str(atom.as_str())
|
||||||
} else {
|
} else {
|
||||||
if self.quoted {
|
if self.quoted {
|
||||||
self.outputter.push_char('\'');
|
self.push_char('\'');
|
||||||
}
|
}
|
||||||
|
|
||||||
for c in atom.as_str().chars() {
|
for c in atom.as_str().chars() {
|
||||||
@@ -442,7 +441,7 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter>
|
|||||||
}
|
}
|
||||||
|
|
||||||
if self.quoted {
|
if self.quoted {
|
||||||
self.outputter.push_char('\'');
|
self.push_char('\'');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -450,15 +449,15 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter>
|
|||||||
|
|
||||||
fn print_char(&mut self, c: char) {
|
fn print_char(&mut self, c: char) {
|
||||||
match c {
|
match c {
|
||||||
'\n' => self.outputter.append("\\n"),
|
'\n' => self.append_str("\\n"),
|
||||||
'\r' => self.outputter.append("\\r"),
|
'\r' => self.append_str("\\r"),
|
||||||
'\t' => self.outputter.append("\\t"),
|
'\t' => self.append_str("\\t"),
|
||||||
'\u{0b}' => self.outputter.append("\\v"), // UTF-8 vertical tab
|
'\u{0b}' => self.append_str("\\v"), // UTF-8 vertical tab
|
||||||
'\u{0c}' => self.outputter.append("\\f"), // UTF-8 form feed
|
'\u{0c}' => self.append_str("\\f"), // UTF-8 form feed
|
||||||
'\u{08}' => self.outputter.append("\\b"), // UTF-8 backspace
|
'\u{08}' => self.append_str("\\b"), // UTF-8 backspace
|
||||||
'\u{07}' => self.outputter.append("\\a"), // UTF-8 alert
|
'\u{07}' => self.append_str("\\a"), // UTF-8 alert
|
||||||
'\x20' ... '\x7e' => self.outputter.push_char(c),
|
'\x20' ... '\x7e' => self.push_char(c),
|
||||||
_ => self.outputter.append(&format!("\\x{:x}", c as u32))
|
_ => self.append_str(&format!("\\x{:x}", c as u32))
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -467,51 +466,51 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter>
|
|||||||
Constant::Atom(ref atom, Some(spec)) => {
|
Constant::Atom(ref atom, Some(spec)) => {
|
||||||
if let Some(ref op) = op {
|
if let Some(ref op) = op {
|
||||||
if self.outputter.ends_with(&format!(" {}", op.as_str())) {
|
if self.outputter.ends_with(&format!(" {}", op.as_str())) {
|
||||||
self.outputter.push_char(' ');
|
self.push_char(' ');
|
||||||
}
|
}
|
||||||
|
|
||||||
self.outputter.push_char('(');
|
self.push_char('(');
|
||||||
}
|
}
|
||||||
|
|
||||||
self.print_atom(atom, Some(spec));
|
self.print_atom(atom, Some(spec));
|
||||||
|
|
||||||
if op.is_some() {
|
if op.is_some() {
|
||||||
self.outputter.push_char(')');
|
self.push_char(')');
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Constant::Atom(ref atom, None) =>
|
Constant::Atom(ref atom, None) =>
|
||||||
push_space_if_amb!(self, atom.as_str(), &op, {
|
push_space_if_amb!(self, atom.as_str(), {
|
||||||
self.print_atom(atom, None);
|
self.print_atom(atom, None);
|
||||||
}),
|
}),
|
||||||
Constant::Char(c) if non_quoted_token(once(c)) =>
|
Constant::Char(c) if non_quoted_token(once(c)) =>
|
||||||
self.print_char(c),
|
self.print_char(c),
|
||||||
Constant::Char(c) =>
|
Constant::Char(c) =>
|
||||||
if self.quoted {
|
if self.quoted {
|
||||||
self.outputter.push_char('\'');
|
self.push_char('\'');
|
||||||
self.print_char(c);
|
self.print_char(c);
|
||||||
self.outputter.push_char('\'');
|
self.push_char('\'');
|
||||||
} else {
|
} else {
|
||||||
self.print_char(c);
|
self.print_char(c);
|
||||||
},
|
},
|
||||||
Constant::EmptyList =>
|
Constant::EmptyList =>
|
||||||
self.outputter.append("[]"),
|
self.append_str("[]"),
|
||||||
Constant::Number(Number::Float(fl)) =>
|
Constant::Number(Number::Float(fl)) =>
|
||||||
if &fl == &OrderedFloat(0f64) {
|
if &fl == &OrderedFloat(0f64) {
|
||||||
push_space_if_amb!(self, "0", &op, {
|
push_space_if_amb!(self, "0", {
|
||||||
self.outputter.append("0");
|
self.append_str("0");
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
let output_str = format!("{}", fl);
|
let output_str = format!("{}", fl);
|
||||||
|
|
||||||
push_space_if_amb!(self, &output_str, &op, {
|
push_space_if_amb!(self, &output_str, {
|
||||||
self.outputter.append(&output_str);
|
self.append_str(&output_str);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
Constant::Number(n) => {
|
Constant::Number(n) => {
|
||||||
let output_str = format!("{}", n);
|
let output_str = format!("{}", n);
|
||||||
|
|
||||||
push_space_if_amb!(self, &output_str, &op, {
|
push_space_if_amb!(self, &output_str, {
|
||||||
self.outputter.append(&output_str);
|
self.append_str(&output_str);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
Constant::String(s) =>
|
Constant::String(s) =>
|
||||||
@@ -524,20 +523,20 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter>
|
|||||||
}
|
}
|
||||||
} else if s.is_expandable() {
|
} else if s.is_expandable() {
|
||||||
if !self.at_cdr(" | _") {
|
if !self.at_cdr(" | _") {
|
||||||
self.outputter.push_char('_');
|
self.push_char('_');
|
||||||
}
|
}
|
||||||
} else if !self.at_cdr("") {
|
} else if !self.at_cdr("") {
|
||||||
self.outputter.append("[]");
|
self.append_str("[]");
|
||||||
}
|
}
|
||||||
} else { // for now, == DoubleQuotes::Atom
|
} else { // for now, == DoubleQuotes::Atom
|
||||||
let borrowed_str = s.borrow();
|
let borrowed_str = s.borrow();
|
||||||
|
|
||||||
self.outputter.append("\"");
|
self.push_char('"');
|
||||||
self.outputter.append(&borrowed_str[s.cursor() ..]);
|
self.append_str(&borrowed_str[s.cursor() ..]);
|
||||||
self.outputter.append("\"");
|
self.push_char('"');
|
||||||
},
|
},
|
||||||
Constant::Usize(i) =>
|
Constant::Usize(i) =>
|
||||||
self.outputter.append(&format!("u{}", i))
|
self.append_str(&format!("u{}", i))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -556,7 +555,7 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter>
|
|||||||
fn handle_heap_term(&mut self, iter: &mut HCPreOrderIterator, op: Option<DirectedOp>,
|
fn handle_heap_term(&mut self, iter: &mut HCPreOrderIterator, op: Option<DirectedOp>,
|
||||||
is_functor_redirect: bool)
|
is_functor_redirect: bool)
|
||||||
{
|
{
|
||||||
let heap_val = match self.check_for_seen(iter, &op) {
|
let heap_val = match self.check_for_seen(iter) {
|
||||||
Some(heap_val) => heap_val,
|
Some(heap_val) => heap_val,
|
||||||
None => return
|
None => return
|
||||||
};
|
};
|
||||||
@@ -583,15 +582,9 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter>
|
|||||||
if add_brackets {
|
if add_brackets {
|
||||||
self.state_stack.push(TokenOrRedirect::Open);
|
self.state_stack.push(TokenOrRedirect::Open);
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(op) = op {
|
|
||||||
if !add_brackets && self.outputter.ends_with(&format!(" {}", op.as_str())) {
|
|
||||||
self.state_stack.push(TokenOrRedirect::Space);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
HeapCellValue::NamedStr(0, name, fixity) =>
|
HeapCellValue::NamedStr(0, name, fixity) =>
|
||||||
push_space_if_amb!(self, name.as_str(), &op, {
|
push_space_if_amb!(self, name.as_str(), {
|
||||||
let ct = ClauseType::from(name, 0, fixity);
|
let ct = ClauseType::from(name, 0, fixity);
|
||||||
self.format_clause(iter, 0, ct);
|
self.format_clause(iter, 0, ct);
|
||||||
}),
|
}),
|
||||||
@@ -601,7 +594,7 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter>
|
|||||||
},
|
},
|
||||||
HeapCellValue::Addr(Addr::Con(Constant::EmptyList)) =>
|
HeapCellValue::Addr(Addr::Con(Constant::EmptyList)) =>
|
||||||
if !self.at_cdr("") {
|
if !self.at_cdr("") {
|
||||||
self.outputter.append("[]");
|
self.append_str("[]");
|
||||||
},
|
},
|
||||||
HeapCellValue::Addr(Addr::Con(c)) =>
|
HeapCellValue::Addr(Addr::Con(c)) =>
|
||||||
self.print_constant(c, &op),
|
self.print_constant(c, &op),
|
||||||
@@ -613,8 +606,8 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter>
|
|||||||
},
|
},
|
||||||
HeapCellValue::Addr(addr) =>
|
HeapCellValue::Addr(addr) =>
|
||||||
if let Some(offset_str) = self.offset_as_string(addr) {
|
if let Some(offset_str) = self.offset_as_string(addr) {
|
||||||
push_space_if_amb!(self, &offset_str, &op, {
|
push_space_if_amb!(self, &offset_str, {
|
||||||
self.outputter.append(offset_str.as_str());
|
self.append_str(offset_str.as_str());
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -624,8 +617,8 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter>
|
|||||||
let len = self.outputter.len();
|
let len = self.outputter.len();
|
||||||
|
|
||||||
if self.outputter.ends_with(" | ") {
|
if self.outputter.ends_with(" | ") {
|
||||||
self.outputter.truncate(len - 3);
|
self.outputter.truncate(len - " | ".len());
|
||||||
self.outputter.append(tr);
|
self.append_str(tr);
|
||||||
|
|
||||||
true
|
true
|
||||||
} else {
|
} else {
|
||||||
@@ -644,31 +637,29 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter>
|
|||||||
TokenOrRedirect::Op(atom, spec) =>
|
TokenOrRedirect::Op(atom, spec) =>
|
||||||
self.print_atom(&atom, Some(spec)),
|
self.print_atom(&atom, Some(spec)),
|
||||||
TokenOrRedirect::NumberedVar(num_var) =>
|
TokenOrRedirect::NumberedVar(num_var) =>
|
||||||
self.outputter.append(num_var.as_str()),
|
self.append_str(num_var.as_str()),
|
||||||
TokenOrRedirect::CompositeRedirect(op) =>
|
TokenOrRedirect::CompositeRedirect(op) =>
|
||||||
self.handle_heap_term(&mut iter, Some(op), false),
|
self.handle_heap_term(&mut iter, Some(op), false),
|
||||||
TokenOrRedirect::FunctorRedirect =>
|
TokenOrRedirect::FunctorRedirect =>
|
||||||
self.handle_heap_term(&mut iter, None, true),
|
self.handle_heap_term(&mut iter, None, true),
|
||||||
TokenOrRedirect::Space =>
|
|
||||||
self.outputter.push_char(' '),
|
|
||||||
TokenOrRedirect::Close =>
|
TokenOrRedirect::Close =>
|
||||||
self.outputter.push_char(')'),
|
self.push_char(')'),
|
||||||
TokenOrRedirect::Open =>
|
TokenOrRedirect::Open =>
|
||||||
self.outputter.push_char('('),
|
self.push_char('('),
|
||||||
TokenOrRedirect::OpenList(delimit) =>
|
TokenOrRedirect::OpenList(delimit) =>
|
||||||
if !self.at_cdr(", ") {
|
if !self.at_cdr(", ") {
|
||||||
self.outputter.push_char('[');
|
self.push_char('[');
|
||||||
} else {
|
} else {
|
||||||
delimit.set(false);
|
delimit.set(false);
|
||||||
},
|
},
|
||||||
TokenOrRedirect::CloseList(delimit) =>
|
TokenOrRedirect::CloseList(delimit) =>
|
||||||
if delimit.get() {
|
if delimit.get() {
|
||||||
self.outputter.push_char(']');
|
self.push_char(']');
|
||||||
},
|
},
|
||||||
TokenOrRedirect::HeadTailSeparator =>
|
TokenOrRedirect::HeadTailSeparator =>
|
||||||
self.outputter.append(" | "),
|
self.append_str(" | "),
|
||||||
TokenOrRedirect::Comma =>
|
TokenOrRedirect::Comma =>
|
||||||
self.outputter.append(", ")
|
self.append_str(", ")
|
||||||
}
|
}
|
||||||
} else if !iter.stack().is_empty() {
|
} else if !iter.stack().is_empty() {
|
||||||
self.handle_heap_term(&mut iter, None, false);
|
self.handle_heap_term(&mut iter, None, false);
|
||||||
|
|||||||
26
src/tests.rs
26
src/tests.rs
@@ -6,6 +6,7 @@ use prolog::toplevel::*;
|
|||||||
|
|
||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
use std::mem::swap;
|
use std::mem::swap;
|
||||||
|
use std::ops::{Range, RangeFrom};
|
||||||
|
|
||||||
pub struct TestOutputter {
|
pub struct TestOutputter {
|
||||||
results: Vec<HashSet<String>>,
|
results: Vec<HashSet<String>>,
|
||||||
@@ -50,9 +51,8 @@ impl HCValueOutputter for TestOutputter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn insert_from_end(&mut self, idx: usize, c: char) {
|
fn insert(&mut self, idx: usize, c: char) {
|
||||||
let len = self.focus.len();
|
self.focus.insert(idx, c);
|
||||||
self.focus.insert(len - idx, c);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn result(self) -> Self::Output {
|
fn result(self) -> Self::Output {
|
||||||
@@ -70,6 +70,14 @@ impl HCValueOutputter for TestOutputter {
|
|||||||
fn truncate(&mut self, len: usize) {
|
fn truncate(&mut self, len: usize) {
|
||||||
self.focus.truncate(len);
|
self.focus.truncate(len);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn range(&self, index: Range<usize>) -> &str {
|
||||||
|
&self.focus.as_str()[index]
|
||||||
|
}
|
||||||
|
|
||||||
|
fn range_from(&self, index: RangeFrom<usize>) -> &str {
|
||||||
|
&self.focus.as_str()[index]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn collect_test_output(wam: &mut Machine, alloc_locs: AllocVarDict, mut heap_locs: HeapVarDict)
|
pub fn collect_test_output(wam: &mut Machine, alloc_locs: AllocVarDict, mut heap_locs: HeapVarDict)
|
||||||
@@ -1689,6 +1697,18 @@ fn test_queries_on_builtins()
|
|||||||
[["X = (:-):-(:-)"]]);
|
[["X = (:-):-(:-)"]]);
|
||||||
assert_prolog_success!(&mut wam, "?- X = (a:-b,c).",
|
assert_prolog_success!(&mut wam, "?- X = (a:-b,c).",
|
||||||
[["X = a:-b,c"]]);
|
[["X = a:-b,c"]]);
|
||||||
|
assert_prolog_success!(&mut wam, "?- X = f((f:-a,b,c)).",
|
||||||
|
[["X = f((f:-a,b,c))"]]);
|
||||||
|
assert_prolog_success!(&mut wam, "?- X = f((f:-a,(b,c))).",
|
||||||
|
[["X = f((f:-a,b,c))"]]);
|
||||||
|
assert_prolog_success!(&mut wam, "?- X = f((a,b,c)).",
|
||||||
|
[["X = f((a,b,c))"]]);
|
||||||
|
assert_prolog_success!(&mut wam, "?- X = f((a,(b,c))).",
|
||||||
|
[["X = f((a,b,c))"]]);
|
||||||
|
assert_prolog_success!(&mut wam, "?- X = f(((a,b),c)).",
|
||||||
|
[["X = f(((a,b),c))"]]);
|
||||||
|
assert_prolog_success!(&mut wam, "?- X = f(((a,b),(c, d))).",
|
||||||
|
[["X = f(((a,b),c,d))"]]);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|||||||
Reference in New Issue
Block a user