use prolog::ast::*;
+use prolog::num::*;
use prolog::heap_iter::*;
use prolog::machine::machine_state::MachineState;
use prolog::ordered_float::OrderedFloat;
#[derive(Clone)]
pub enum TokenOrRedirect {
Atom(ClauseName),
+ NumberedVar(String),
Redirect,
Open,
Close,
// this can be overloaded to handle special cases, falling back on the default of
// format_struct when convenient.
- fn format_clause(&self, usize, ClauseType, &mut Vec<TokenOrRedirect>);
+ fn format_clause(&self, &mut HCPreOrderIterator, usize, ClauseType, &mut Vec<TokenOrRedirect>);
}
pub trait HCValueOutputter {
}
// the 'classic' display corresponding to the display predicate.
-pub struct DisplayFormatter {}
+pub struct WriteqFormatter {}
-impl HCValueFormatter for DisplayFormatter {
- fn format_clause(&self, arity: usize, ct: ClauseType, state_stack: &mut Vec<TokenOrRedirect>)
+fn is_numbered_var(ct: &ClauseType, arity: usize) -> bool {
+ arity == 1 && if let &ClauseType::Named(ref name, _) = ct {
+ name.as_str() == "$VAR"
+ } else {
+ false
+ }
+}
+
+fn print_op(ct: ClauseType, fixity: Fixity, state_stack: &mut Vec<TokenOrRedirect>) {
+ match fixity {
+ Fixity::Post => {
+ state_stack.push(TokenOrRedirect::Atom(ct.name()));
+ state_stack.push(TokenOrRedirect::Redirect);
+ },
+ Fixity::Pre => {
+ state_stack.push(TokenOrRedirect::Redirect);
+ state_stack.push(TokenOrRedirect::Atom(ct.name()));
+ },
+ Fixity::In => {
+ state_stack.push(TokenOrRedirect::Redirect);
+ state_stack.push(TokenOrRedirect::Atom(ct.name()));
+ state_stack.push(TokenOrRedirect::Redirect);
+ }
+ }
+}
+
+impl HCValueFormatter for WriteqFormatter {
+ fn format_clause(&self, iter: &mut HCPreOrderIterator, arity: usize,
+ ct: ClauseType, state_stack: &mut Vec<TokenOrRedirect>)
{
- if ct.fixity().is_some() {
- let mut new_name = String::from("'");
- new_name += ct.name().as_str();
- new_name += "'";
+ static CHAR_CODES: [char; 26] = ['A','B','C','D','E','F','G','H','I','J',
+ 'K','L','M','N','O','P','Q','R','S','T',
+ 'U','V','W','X','Y','Z'];
- self.format_struct(arity, ct.name(), state_stack);
- } else {
- self.format_struct(arity, ct.name(), state_stack);
+ if let Some(fixity) = ct.fixity() {
+ return print_op(ct, fixity, state_stack);
+ } else if is_numbered_var(&ct, arity) {
+ let addr = iter.stack().last().cloned().unwrap();
+
+ // 7.10.4
+ match iter.machine_st.store(iter.machine_st.deref(addr)) {
+ Addr::Con(Constant::Number(Number::Integer(n))) => {
+ iter.stack().pop();
+
+ let i = n.mod_floor(&BigInt::from(26)).to_usize().unwrap();
+ let j = n.div_floor(&BigInt::from(26));
+
+ let mut result = if j.is_zero() {
+ CHAR_CODES[i].to_string()
+ } else {
+ format!("{}{}", CHAR_CODES[i], j)
+ };
+
+ state_stack.push(TokenOrRedirect::NumberedVar(result));
+
+ return;
+ }
+ _ => {}
+ };
}
+
+ self.format_struct(arity, ct.name(), state_stack);
}
}
pub struct TermFormatter {}
impl HCValueFormatter for TermFormatter {
- fn format_clause(&self, arity: usize, ct: ClauseType, state_stack: &mut Vec<TokenOrRedirect>)
+ fn format_clause(&self, _: &mut HCPreOrderIterator, arity: usize, ct: ClauseType,
+ state_stack: &mut Vec<TokenOrRedirect>)
{
if let Some(fixity) = ct.fixity() {
- match fixity {
- Fixity::Post => {
- state_stack.push(TokenOrRedirect::Atom(ct.name()));
- state_stack.push(TokenOrRedirect::Redirect);
- },
- Fixity::Pre => {
- state_stack.push(TokenOrRedirect::Redirect);
- state_stack.push(TokenOrRedirect::Atom(ct.name()));
- },
- Fixity::In => {
- state_stack.push(TokenOrRedirect::Redirect);
- state_stack.push(TokenOrRedirect::Atom(ct.name()));
- state_stack.push(TokenOrRedirect::Redirect);
- }
- }
+ print_op(ct, fixity, state_stack);
} else {
self.format_struct(arity, ct.name(), state_stack);
}
match heap_val {
HeapCellValue::NamedStr(arity, name, fixity) => {
let ct = ClauseType::from(name, arity, fixity);
- self.formatter.format_clause(arity, ct, &mut self.state_stack)
+ self.formatter.format_clause(iter, arity, ct, &mut self.state_stack)
},
HeapCellValue::Addr(Addr::Con(Constant::EmptyList)) =>
if !self.at_cdr("") {
// self.outputter.append(" "),
TokenOrRedirect::Atom(atom) =>
self.outputter.append(atom.as_str()),
+ TokenOrRedirect::NumberedVar(num_var) =>
+ self.outputter.append(num_var.as_str()),
TokenOrRedirect::Redirect =>
self.handle_heap_term(&mut iter),
TokenOrRedirect::Close =>