From: Mark Thom Date: Wed, 29 Apr 2020 00:03:04 +0000 (-0600) Subject: print rational numbers using the rdiv operator when defined (#413) X-Git-Tag: v0.8.123~99 X-Git-Url: https://git.sagredo.dev/?a=commitdiff_plain;h=0e1226573a97169fd9d1428c89aa522dd66fee8d;p=scryer-prolog.git print rational numbers using the rdiv operator when defined (#413) --- diff --git a/src/prolog/arithmetic.rs b/src/prolog/arithmetic.rs index fb20678e..db4317b7 100644 --- a/src/prolog/arithmetic.rs +++ b/src/prolog/arithmetic.rs @@ -789,6 +789,13 @@ impl<'a> TryFrom<&'a HeapCellValue> for Number { } } +impl<'a> From<&'a Integer> for Number { + #[inline] + fn from(src: &'a Integer) -> Self { + Number::Integer(Rc::new(Integer::from(src))) + } +} + // Computes n ^ power. Ignores the sign of power. pub fn binary_pow(mut n: Integer, power: &Integer) -> Integer { let mut power = Integer::from(power.abs_ref()); diff --git a/src/prolog/heap_print.rs b/src/prolog/heap_print.rs index 5e36c35c..5ddbcdd4 100644 --- a/src/prolog/heap_print.rs +++ b/src/prolog/heap_print.rs @@ -7,7 +7,7 @@ use crate::prolog::machine::heap::*; use crate::prolog::machine::machine_indices::*; use crate::prolog::machine::machine_state::*; use crate::prolog::ordered_float::OrderedFloat; -use crate::prolog::rug::Integer; +use crate::prolog::rug::{Integer, Rational}; use indexmap::{IndexMap, IndexSet}; @@ -170,6 +170,7 @@ enum TokenOrRedirect { NumberedVar(String), CompositeRedirect(usize, DirectedOp), FunctorRedirect(usize), + Number(Number, Option), Open, Close, Comma, @@ -989,6 +990,10 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> { }); } } + Number::Rational(r) => { + self.print_rational(&r, add_brackets); + return; + } n => { let output_str = format!("{}", n); @@ -1003,6 +1008,71 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> { } } + fn print_rational(&mut self, r: &Rational, add_brackets: bool) { + match self.op_dir.get(&(clause_name!("rdiv"), Fixity::In)) { + Some(OpDirValue(ref spec, _)) => { + if add_brackets { + self.state_stack.push(TokenOrRedirect::Close); + } + + let rdiv_ct = clause_name!("rdiv"); + + let left_directed_op = + if spec.prec() > 0 { + Some(DirectedOp::Left(rdiv_ct.clone(), spec.clone())) + } else { + None + }; + + let right_directed_op = + if spec.prec() > 0 { + Some(DirectedOp::Right(rdiv_ct.clone(), spec.clone())) + } else { + None + }; + + if spec.prec() > 0 { + self.state_stack.push(TokenOrRedirect::Number( + Number::from(r.denom()), + left_directed_op, + )); + + self.state_stack.push(TokenOrRedirect::Op( + rdiv_ct, + spec.clone(), + )); + + self.state_stack.push(TokenOrRedirect::Number( + Number::from(r.numer()), + right_directed_op, + )); + } else { + self.state_stack.push(TokenOrRedirect::Close); + + self.state_stack.push(TokenOrRedirect::Number( + Number::from(r.denom()), + None, + )); + + self.state_stack.push(TokenOrRedirect::Comma); + + self.state_stack.push(TokenOrRedirect::Number( + Number::from(r.numer()), + None, + )); + + self.state_stack.push(TokenOrRedirect::Open); + self.state_stack.push(TokenOrRedirect::Atom(rdiv_ct)); + } + + return; + } + _ => { + unreachable!() + } + } + } + fn print_char(&mut self, is_quoted: bool, c: char) { if non_quoted_token(once(c)) { @@ -1431,6 +1501,7 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> { } } TokenOrRedirect::HeadTailSeparator => self.append_str("|"), + TokenOrRedirect::Number(n, op) => self.print_number(n, &op), TokenOrRedirect::Comma => self.append_str(","), TokenOrRedirect::Space => self.push_char(' '), TokenOrRedirect::LeftCurly => self.push_char('{'),