From 21f6415b2914d2ca55b00826130e088ace61b5fb Mon Sep 17 00:00:00 2001
From: arthur-adjedj <arthur.adjedj@gmail.com>
Date: Wed, 2 Nov 2022 18:13:57 +0100
Subject: [PATCH] feat(universe) : pretty print universes

---
 kernel/src/universe.rs | 55 ++++++++++++++++++++++++++++++++++++------
 1 file changed, 47 insertions(+), 8 deletions(-)

diff --git a/kernel/src/universe.rs b/kernel/src/universe.rs
index ad8a07c4..1da5d8ee 100644
--- a/kernel/src/universe.rs
+++ b/kernel/src/universe.rs
@@ -1,20 +1,16 @@
+use std::fmt::Display;
+use std::fmt::Formatter;
 use std::ops::Add;
 
-use derive_more::Display;
-
-#[derive(Clone, Debug, Default, Display, PartialEq, Eq)]
+#[derive(Clone, Debug, Default, PartialEq, Eq)]
 pub enum UniverseLevel {
     #[default]
-    #[display(fmt = "0")]
     Zero,
 
-    #[display(fmt = "({}) + 1", _0)]
     Succ(Box<UniverseLevel>),
 
-    #[display(fmt = "max ({}) ({})", _0, _1)]
     Max(Box<UniverseLevel>, Box<UniverseLevel>),
 
-    #[display(fmt = "u{}", _0)]
     Var(usize),
 }
 
@@ -44,9 +40,53 @@ impl From<usize> for UniverseLevel {
     }
 }
 
+impl Display for UniverseLevel {
+    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
+        write!(f, "{}", self.pretty_print())
+    }
+}
+
 use UniverseLevel::*;
 
 impl UniverseLevel {
+    /// Helper function for pretty printing, if universe doesn't contain any variable then it gets printed as a decimal number.
+    fn to_numeral(&self) -> Option<usize> {
+        match self {
+            Zero => Some(0),
+            Succ(box u) => u.to_numeral().map(|n| n + 1),
+            Max(box n, box m) => n
+                .to_numeral()
+                .and_then(|n| m.to_numeral().map(|m| n.max(m))),
+            _ => None,
+        }
+    }
+
+    /// Helper function for pretty printing, if universe is of the form Succ(Succ(...(Succ(u))...)) then it gets printed as u+n.
+    fn plus(&self) -> (UniverseLevel, usize) {
+        match self {
+            Succ(box u) => {
+                let (u, n) = u.plus();
+                (u, n + 1)
+            }
+            _ => (self.clone(), 0),
+        }
+    }
+    /// Pretty prints universe levels, used to impl Display for UniverseLevel.
+    fn pretty_print(&self) -> String {
+        match self.to_numeral() {
+            Some(n) => n.to_string(),
+            None => match self {
+                Zero => unreachable!("Zero is a numeral"),
+                Succ(_) => match self.plus() {
+                    (u, 0) => format!("{}", u.pretty_print()),
+                    (u, n) => format!("{} + {}", u.pretty_print(), n),
+                },
+                Max(box n, box m) => format!("max ({}) ({})", n.pretty_print(), m.pretty_print()),
+                Var(n) => format!("u{}", n),
+            },
+        }
+    }
+
     pub fn univ_vars(self) -> usize {
         match self {
             Zero => 0,
@@ -88,7 +128,6 @@ mod tests {
 
     #[test]
     fn univ_eq() {
-        assert!(format!("{}", Max(box Zero, box Zero)) == "max (0) (0)");
         assert!(&Zero.is_eq(&Default::default()));
         assert!(!&Zero.is_eq(&Succ(box Zero)));
         assert!(!&Succ(box Zero).is_eq(&Zero));
-- 
GitLab