From ce9501df692ca872792981b888a1940bf5a44b61 Mon Sep 17 00:00:00 2001 From: Viktor Kleen Date: Fri, 9 Jun 2023 07:59:44 +0000 Subject: [PATCH] Replace Term::deep_repr by the pretty printer (#1262) * Replace Term::deep_repr by the pretty printer * Move `BoxAllocator` back to a more local scope --- src/bin/nickel.rs | 6 +-- src/pretty.rs | 19 ++++++++-- src/repl/rustyline_frontend.rs | 4 +- src/repl/simple_frontend.rs | 6 +-- src/term/mod.rs | 37 +------------------ tests/snapshot/inputs/eval/escaping.ncl | 3 ++ tests/snapshot/inputs/eval/records.ncl | 3 ++ .../snapshot__error_stdout_escaping.ncl.snap | 6 +++ .../snapshot__error_stdout_records.ncl.snap | 6 +++ 9 files changed, 40 insertions(+), 50 deletions(-) create mode 100644 tests/snapshot/inputs/eval/escaping.ncl create mode 100644 tests/snapshot/inputs/eval/records.ncl create mode 100644 tests/snapshot/snapshots/snapshot__error_stdout_escaping.ncl.snap create mode 100644 tests/snapshot/snapshots/snapshot__error_stdout_records.ncl.snap diff --git a/src/bin/nickel.rs b/src/bin/nickel.rs index 413a6e7ac3..e08f846b3e 100644 --- a/src/bin/nickel.rs +++ b/src/bin/nickel.rs @@ -6,7 +6,7 @@ use nickel_lang::program::Program; use nickel_lang::repl::query_print; #[cfg(feature = "repl")] use nickel_lang::repl::rustyline_frontend; -use nickel_lang::term::{RichTerm, Term}; +use nickel_lang::term::RichTerm; use nickel_lang::{serialize, serialize::ExportFormat}; use std::path::{Path, PathBuf}; use std::{ @@ -207,9 +207,7 @@ fn main() { stdout, format, }) => export_doc(&mut program, opts.file.as_ref(), output, stdout, format), - None => program - .eval_full() - .map(|t| println!("{}", Term::from(t).deep_repr())), + None => program.eval_full().map(|t| println!("{t}")), }; if let Err(err) = result { diff --git a/src/pretty.rs b/src/pretty.rs index 1ce9382282..a857bb67d3 100644 --- a/src/pretty.rs +++ b/src/pretty.rs @@ -410,6 +410,17 @@ where } impl<'a, D, A> Pretty<'a, D, A> for RichTerm +where + D: NickelAllocatorExt<'a, A>, + D::Doc: Clone, + A: Clone + 'a, +{ + fn pretty(self, allocator: &'a D) -> DocBuilder<'a, D, A> { + self.as_ref().pretty(allocator) + } +} + +impl<'a, D, A> Pretty<'a, D, A> for &Term where D: NickelAllocatorExt<'a, A>, D::Doc: Clone, @@ -418,7 +429,7 @@ where fn pretty(self, allocator: &'a D) -> DocBuilder<'a, D, A> { use Term::*; - match self.as_ref() { + match self { Null => allocator.text("null"), Bool(v) => allocator.as_string(v), Num(n) => allocator.as_string(format!("{}", n.to_sci())), @@ -453,8 +464,8 @@ where // TODO Pattern destructuring to implement. FunPattern(..) => { let mut params = vec![]; - let mut rt = &self; - while let FunPattern(id, dst, t) = rt.as_ref() { + let mut rt = self; + while let FunPattern(id, dst, t) = rt { params.push(if let Some(id) = id { allocator .as_string(id) @@ -462,7 +473,7 @@ where } else { dst.pretty(allocator) }); - rt = t; + rt = t.as_ref(); } allocator .text("fun") diff --git a/src/repl/rustyline_frontend.rs b/src/repl/rustyline_frontend.rs index 2c942f997d..109014301f 100644 --- a/src/repl/rustyline_frontend.rs +++ b/src/repl/rustyline_frontend.rs @@ -95,7 +95,7 @@ pub fn repl(histfile: PathBuf, color_opt: ColorOpt) -> Result<(), InitError> { }), Ok(Command::Print(exp)) => { match repl.eval_full(&exp) { - Ok(EvalResult::Evaluated(rt)) => println!("{}\n", rt.as_ref().deep_repr()), + Ok(EvalResult::Evaluated(rt)) => println!("{rt}"), Ok(EvalResult::Bound(_)) => (), Err(err) => program::report(repl.cache_mut(), err, color_opt), }; @@ -120,7 +120,7 @@ pub fn repl(histfile: PathBuf, color_opt: ColorOpt) -> Result<(), InitError> { } Ok(line) => { match repl.eval_full(&line) { - Ok(EvalResult::Evaluated(rt)) => println!("{}\n", rt.as_ref().deep_repr()), + Ok(EvalResult::Evaluated(rt)) => println!("{rt}\n"), Ok(EvalResult::Bound(_)) => (), Err(err) => program::report(repl.cache_mut(), err, color_opt), }; diff --git a/src/repl/simple_frontend.rs b/src/repl/simple_frontend.rs index 3ae256532a..e32bcf91c1 100644 --- a/src/repl/simple_frontend.rs +++ b/src/repl/simple_frontend.rs @@ -65,7 +65,7 @@ pub fn input(repl: &mut R, line: &str) -> Result repl .eval_full(&exp) .map(|res| match res { - EvalResult::Evaluated(rt) => InputResult::Success(rt.as_ref().deep_repr()), + EvalResult::Evaluated(rt) => InputResult::Success(format!("{rt}\n")), EvalResult::Bound(_) => InputResult::Blank, }) .map_err(InputError::from), @@ -82,9 +82,7 @@ pub fn input(repl: &mut R, line: &str) -> Result { - InputResult::Success(format!("{}\n", rt.as_ref().deep_repr())) - } + EvalResult::Evaluated(rt) => InputResult::Success(format!("{rt}\n")), EvalResult::Bound(_) => InputResult::Success(String::new()), }) .map_err(InputError::from) diff --git a/src/term/mod.rs b/src/term/mod.rs index 361facfe87..9e2418a09f 100644 --- a/src/term/mod.rs +++ b/src/term/mod.rs @@ -742,40 +742,6 @@ impl Term { } } - /// Return a deep string representation of a term, used for printing in the REPL - pub fn deep_repr(&self) -> String { - match self { - Term::Record(r) | Term::RecRecord(r, ..) => { - let fields_str: Vec = r - .fields - .iter() - .map(|(ident, field)| { - if let Some(ref value) = field.value { - format!("{} = {}", ident, value.as_ref().deep_repr()) - } else { - format!("{ident}") - } - }) - .collect(); - - let suffix = match self { - Term::RecRecord(_, dyn_fields, ..) if !dyn_fields.is_empty() => ", ..", - _ => "", - }; - - format!("{{ {}{} }}", fields_str.join(", "), suffix) - } - Term::Array(elements, _) => { - let elements_str: Vec = elements - .iter() - .map(|term| term.as_ref().deep_repr()) - .collect(); - format!("[ {} ]", elements_str.join(", ")) - } - _ => self.shallow_repr(), - } - } - /// Determine if a term is in evaluated from, called weak head normal form (WHNF). pub fn is_whnf(&self) -> bool { match self { @@ -1734,9 +1700,8 @@ impl From for RichTerm { impl std::fmt::Display for RichTerm { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { use crate::pretty::*; - use pretty::BoxAllocator; - let allocator = BoxAllocator; + let allocator = pretty::BoxAllocator; let doc: DocBuilder<_, ()> = self.clone().pretty(&allocator); doc.render_fmt(80, f) diff --git a/tests/snapshot/inputs/eval/escaping.ncl b/tests/snapshot/inputs/eval/escaping.ncl new file mode 100644 index 0000000000..e67e7e3a67 --- /dev/null +++ b/tests/snapshot/inputs/eval/escaping.ncl @@ -0,0 +1,3 @@ +# capture = 'stdout' +# command = [] +"a\"bcd\"" diff --git a/tests/snapshot/inputs/eval/records.ncl b/tests/snapshot/inputs/eval/records.ncl new file mode 100644 index 0000000000..747a3aeda0 --- /dev/null +++ b/tests/snapshot/inputs/eval/records.ncl @@ -0,0 +1,3 @@ +# capture = 'stdout' +# command = [] +{ a = true, b | Number = 6 * 7 } diff --git a/tests/snapshot/snapshots/snapshot__error_stdout_escaping.ncl.snap b/tests/snapshot/snapshots/snapshot__error_stdout_escaping.ncl.snap new file mode 100644 index 0000000000..1ef52987b3 --- /dev/null +++ b/tests/snapshot/snapshots/snapshot__error_stdout_escaping.ncl.snap @@ -0,0 +1,6 @@ +--- +source: tests/snapshot/main.rs +expression: out +--- +"a\"bcd\"" + diff --git a/tests/snapshot/snapshots/snapshot__error_stdout_records.ncl.snap b/tests/snapshot/snapshots/snapshot__error_stdout_records.ncl.snap new file mode 100644 index 0000000000..008f2a8588 --- /dev/null +++ b/tests/snapshot/snapshots/snapshot__error_stdout_records.ncl.snap @@ -0,0 +1,6 @@ +--- +source: tests/snapshot/main.rs +expression: out +--- +{ a = true, b | Number = 42, } +