]> Repositorios git - scryer-prolog.git/commitdiff
print rational numbers using the rdiv operator when defined (#413)
authorMark Thom <[email protected]>
Wed, 29 Apr 2020 00:03:04 +0000 (18:03 -0600)
committerMark Thom <[email protected]>
Wed, 29 Apr 2020 00:03:04 +0000 (18:03 -0600)
src/prolog/arithmetic.rs
src/prolog/heap_print.rs

index fb20678e4ee7b951b2de70fb5ea3f2668705950b..db4317b723f68329595200d22d9734bba6426110 100644 (file)
@@ -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());
index 5e36c35c564afdcf6bcab07c13a765564831b152..5ddbcdd45362f3116fe2dff70ddb8962abaab1b0 100644 (file)
@@ -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<DirectedOp>),
     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('{'),