From: Mark Thom Date: Tue, 17 Jul 2018 02:12:50 +0000 (-0600) Subject: add numbered vars to writeq X-Git-Tag: v0.8.110~442 X-Git-Url: https://git.sagredo.dev/?a=commitdiff_plain;h=82ff377585772e9be3a50b8a1908ea11b0b8ed81;p=scryer-prolog.git add numbered vars to writeq --- diff --git a/src/prolog/heap_iter.rs b/src/prolog/heap_iter.rs index 58129249..4b9544e1 100644 --- a/src/prolog/heap_iter.rs +++ b/src/prolog/heap_iter.rs @@ -5,7 +5,7 @@ use std::collections::HashSet; use std::vec::Vec; pub struct HCPreOrderIterator<'a> { - machine_st: &'a MachineState, + pub(crate) machine_st: &'a MachineState, state_stack: Vec } diff --git a/src/prolog/heap_print.rs b/src/prolog/heap_print.rs index e09cc020..6bbe4ef8 100644 --- a/src/prolog/heap_print.rs +++ b/src/prolog/heap_print.rs @@ -1,4 +1,5 @@ use prolog::ast::*; +use prolog::num::*; use prolog::heap_iter::*; use prolog::machine::machine_state::MachineState; use prolog::ordered_float::OrderedFloat; @@ -10,6 +11,7 @@ use std::rc::Rc; #[derive(Clone)] pub enum TokenOrRedirect { Atom(ClauseName), + NumberedVar(String), Redirect, Open, Close, @@ -40,7 +42,7 @@ pub trait HCValueFormatter { // 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); + fn format_clause(&self, &mut HCPreOrderIterator, usize, ClauseType, &mut Vec); } pub trait HCValueOutputter { @@ -99,44 +101,81 @@ impl HCValueOutputter for PrinterOutputter { } // 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) +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) { + 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) { - 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) + fn format_clause(&self, _: &mut HCPreOrderIterator, arity: usize, ct: ClauseType, + state_stack: &mut Vec) { 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); } @@ -303,7 +342,7 @@ impl<'a, Formatter: HCValueFormatter, Outputter: HCValueOutputter> 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("") { @@ -349,6 +388,8 @@ impl<'a, Formatter: HCValueFormatter, Outputter: HCValueOutputter> // 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 => diff --git a/src/prolog/io.rs b/src/prolog/io.rs index 71fdde36..6b78785d 100644 --- a/src/prolog/io.rs +++ b/src/prolog/io.rs @@ -1,7 +1,6 @@ use prolog::ast::*; use prolog::heap_print::*; use prolog::machine::*; -use prolog::ordered_float::OrderedFloat; use termion::raw::IntoRawMode; use termion::input::TermRead; diff --git a/src/prolog/machine/machine_state.rs b/src/prolog/machine/machine_state.rs index 82570099..859a6a40 100644 --- a/src/prolog/machine/machine_state.rs +++ b/src/prolog/machine/machine_state.rs @@ -494,7 +494,7 @@ pub(crate) trait CallPolicy: Any { }, &BuiltInClauseType::Writeq => { let output = machine_st.print_term(machine_st[temp_v!(1)].clone(), - DisplayFormatter {}, + WriteqFormatter {}, PrinterOutputter::new()); println!("{}", output.result());