[sc-437] Implement fmt::Display for more things

This commit is contained in:
Nicolas Abril 2024-02-09 14:58:18 +01:00
parent 25a6926ab1
commit daf34d3784
6 changed files with 110 additions and 106 deletions

View File

@ -216,11 +216,7 @@ impl RunOpts {
|net: &_| {
let net = hvmc_to_net(net, &hvmc_names.hvmc_to_hvml);
let (res_term, errors) = net_to_term(&net, book, labels, self.linear);
println!(
"{}{}\n---------------------------------------",
display_readback_errors(&errors),
res_term.display()
)
println!("{}{}\n---------------------------------------", display_readback_errors(&errors), res_term,)
}
})
}

View File

@ -211,7 +211,7 @@ fn execute_cli_mode(cli: Cli, verbose: &dyn Fn(&hvml::term::Book)) -> Result<(),
println!("\n{}", show_net(&net));
}
println!("{}{}", display_readback_errors(&readback_errors), res_term.display());
println!("{}{}", display_readback_errors(&readback_errors), res_term);
if arg_stats {
println!("\nRWTS : {}", total_rewrites);

View File

@ -1,8 +1,37 @@
use std::fmt::{self, Display};
use super::{
net_to_term::ReadbackError, Book, DefName, Definition, MatchNum, Name, Op, Pattern, Rule, Tag, Term, Type,
};
use std::fmt;
/* Some aux structures for things that are not so simple to display */
struct DisplayFn<F: Fn(&mut fmt::Formatter) -> fmt::Result>(F);
impl<F: Fn(&mut fmt::Formatter) -> fmt::Result> fmt::Display for DisplayFn<F> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.0(f)
}
}
pub struct DisplayJoin<F, S>(pub F, pub S);
impl<F, I, S> fmt::Display for DisplayJoin<F, S>
where
F: (Fn() -> I),
I: Iterator,
I::Item: fmt::Display,
S: fmt::Display,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
for (i, x) in self.0().enumerate() {
if i != 0 {
self.1.fmt(f)?;
}
x.fmt(f)?;
}
Ok(())
}
}
macro_rules! display {
($($x:tt)*) => {
@ -10,83 +39,63 @@ macro_rules! display {
};
}
impl Term {
fn display_app<'a>(&'a self, tag: &'a Tag) -> impl Display + 'a {
DisplayFn(move |f| match self {
Term::App { tag: tag2, fun, arg } if tag2 == tag => {
write!(f, "{} {}", fun.display_app(tag), arg.display())
}
_ => write!(f, "{}", self.display()),
})
}
pub fn display(&self) -> impl Display + '_ {
DisplayFn(move |f| match self {
/* The actual display implementations */
impl fmt::Display for Term {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Term::Lam { tag, nam, bod } => {
write!(f, "{}λ{} {}", tag.display_padded(), nam.as_ref().map_or("*", |x| x.as_str()), bod.display())
write!(f, "{}λ{} {}", tag.display_padded(), var_as_str(nam), bod)
}
Term::Var { nam } => write!(f, "{nam}"),
Term::Chn { tag, nam, bod } => {
write!(f, "{}λ${} {}", tag.display_padded(), nam, bod.display())
write!(f, "{}λ${} {}", tag.display_padded(), nam, bod)
}
Term::Lnk { nam } => write!(f, "${nam}"),
Term::Let { pat, val, nxt } => {
write!(f, "let {} = {}; {}", pat, val.display(), nxt.display())
write!(f, "let {} = {}; {}", pat, val, nxt)
}
Term::Ref { def_name } => write!(f, "{def_name}"),
Term::App { tag, fun, arg } => {
write!(f, "{}({} {})", tag.display_padded(), fun.display_app(tag), arg.display())
write!(f, "{}({} {})", tag.display_padded(), fun.display_app(tag), arg)
}
Term::Match { scrutinee, arms } => {
write!(
f,
"match {} {{ {} }}",
scrutinee.display(),
DisplayJoin(|| arms.iter().map(|(pat, term)| display!("{}: {}", pat, term.display())), "; "),
scrutinee,
DisplayJoin(|| arms.iter().map(|(pat, term)| display!("{}: {}", pat, term)), "; "),
)
}
Term::Dup { tag, fst, snd, val, nxt } => write!(
f,
"let {}{{{} {}}} = {}; {}",
tag.display(),
fst.as_ref().map_or("*", |x| x.as_str()),
snd.as_ref().map_or("*", |x| x.as_str()),
val.display(),
nxt.display()
),
Term::Dup { tag, fst, snd, val, nxt } => {
write!(f, "let {}{{{} {}}} = {}; {}", tag, var_as_str(fst), var_as_str(snd), val, nxt)
}
Term::Sup { tag, fst, snd } => {
write!(f, "{}{{{} {}}}", tag.display(), fst.display(), snd.display())
write!(f, "{}{{{} {}}}", tag, fst, snd)
}
Term::Era => write!(f, "*"),
Term::Num { val } => write!(f, "{val}"),
Term::Str { val } => write!(f, "{val:?}"),
Term::Opx { op, fst, snd } => {
write!(f, "({} {} {})", op, fst.display(), snd.display())
write!(f, "({} {} {})", op, fst, snd)
}
Term::Tup { fst, snd } => write!(f, "({}, {})", fst.display(), snd.display()),
Term::Tup { fst, snd } => write!(f, "({}, {})", fst, snd),
Term::List { els } => {
write!(f, "[{}]", DisplayJoin(|| els.iter().map(|el| display!("{}", el.display())), ", "),)
write!(f, "[{}]", DisplayJoin(|| els.iter(), ", "),)
}
Term::Invalid => write!(f, "<Invalid>"),
})
}
}
}
impl Tag {
pub fn display_padded(&self) -> impl Display + '_ {
DisplayFn(move |f| match self {
Tag::Named(name) => write!(f, "#{name} "),
Tag::Numeric(num) => write!(f, "#{num} "),
Tag::Auto => Ok(()),
Tag::Static => Ok(()),
})
}
pub fn display(&self) -> impl Display + '_ {
DisplayFn(move |f| match self {
impl fmt::Display for Tag {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Tag::Named(name) => write!(f, "#{name}"),
Tag::Numeric(num) => write!(f, "#{num}"),
Tag::Auto => Ok(()),
Tag::Static => Ok(()),
})
}
}
}
@ -100,31 +109,31 @@ impl fmt::Display for Pattern {
}
Pattern::Num(num) => write!(f, "{num}"),
Pattern::Tup(fst, snd) => write!(f, "({}, {})", fst, snd,),
Pattern::List(pats) => write!(f, "[{}]", DisplayJoin(|| pats.iter().map(|p| display!("{p}")), ", ")),
Pattern::List(pats) => write!(f, "[{}]", DisplayJoin(|| pats.iter(), ", ")),
}
}
}
impl Rule {
pub fn display<'a>(&'a self, def_name: &'a DefName) -> impl Display + 'a {
pub fn display<'a>(&'a self, def_name: &'a DefName) -> impl fmt::Display + 'a {
display!(
"({}{}) = {}",
def_name,
DisplayJoin(|| self.pats.iter().map(|x| display!(" {x}")), ""),
self.body.display()
self.body
)
}
}
impl Definition {
pub fn display(&self) -> impl Display + '_ {
DisplayJoin(|| self.rules.iter().map(|x| x.display(&self.name)), "\n")
impl fmt::Display for Definition {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", DisplayJoin(|| self.rules.iter().map(|x| x.display(&self.name)), "\n"))
}
}
impl fmt::Display for Book {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", DisplayJoin(|| self.defs.values().map(|x| x.display()), "\n\n"))
write!(f, "{}", DisplayJoin(|| self.defs.values(), "\n\n"))
}
}
@ -180,31 +189,29 @@ impl fmt::Display for Type {
}
}
}
struct DisplayFn<F: Fn(&mut fmt::Formatter) -> fmt::Result>(F);
impl<F: Fn(&mut fmt::Formatter) -> fmt::Result> Display for DisplayFn<F> {
impl fmt::Display for ReadbackError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.0(f)
}
}
match self {
ReadbackError::InvalidNumericMatch => write!(f, "Invalid Numeric Match"),
ReadbackError::InvalidNumericOp => write!(f, "Invalid Numeric Operation"),
ReadbackError::ReachedRoot => write!(f, "Reached Root"),
ReadbackError::Cyclic => write!(f, "Cyclic Term"),
ReadbackError::InvalidBind => write!(f, "Invalid Bind"),
ReadbackError::InvalidAdt => write!(f, "Invalid Adt"),
ReadbackError::UnexpectedTag(exp, fnd) => {
write!(f, "Unexpected tag found during Adt readback, expected '{exp}', but found ")?;
pub struct DisplayJoin<F, S>(pub F, pub S);
impl<F, I, S> Display for DisplayJoin<F, S>
where
F: (Fn() -> I),
I: Iterator,
I::Item: Display,
S: Display,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
for (i, x) in self.0().enumerate() {
if i != 0 {
self.1.fmt(f)?;
match fnd {
Tag::Static => write!(f, "no tag"),
_ => write!(f, "'{fnd}'"),
}
}
ReadbackError::InvalidAdtMatch => write!(f, "Invalid Adt Match"),
ReadbackError::InvalidStrTerm(term) => {
write!(f, "Invalid String Character value '{term}'")
}
x.fmt(f)?;
}
Ok(())
}
}
@ -220,14 +227,14 @@ pub fn display_readback_errors(errs: &[ReadbackError]) -> impl fmt::Display + '_
if err.can_count() {
*err_counts.entry(err).or_insert(0) += 1;
} else {
writeln!(f, "{}", err.display())?;
writeln!(f, "{err}")?;
}
}
for (err, count) in err_counts {
write!(f, "{}", err.display())?;
write!(f, "{err}")?;
if count > 1 {
writeln!(f, " with {} occurrences", count)?;
writeln!(f, " ({count} occurrences)")?;
}
}
@ -235,27 +242,28 @@ pub fn display_readback_errors(errs: &[ReadbackError]) -> impl fmt::Display + '_
})
}
impl ReadbackError {
pub fn display(&self) -> impl Display + '_ {
impl Term {
fn display_app<'a>(&'a self, tag: &'a Tag) -> impl fmt::Display + 'a {
DisplayFn(move |f| match self {
ReadbackError::InvalidNumericMatch => write!(f, "Invalid Numeric Match"),
ReadbackError::InvalidNumericOp => write!(f, "Invalid Numeric Operation"),
ReadbackError::ReachedRoot => write!(f, "Reached Root"),
ReadbackError::Cyclic => write!(f, "Cyclic Term"),
ReadbackError::InvalidBind => write!(f, "Invalid Bind"),
ReadbackError::InvalidAdt => write!(f, "Invalid Adt"),
ReadbackError::UnexpectedTag(exp, fnd) => {
write!(f, "Unexpected tag found during Adt readback, expected '{}', but found ", exp.display())?;
match fnd {
Tag::Static => write!(f, "no tag"),
_ => write!(f, "'{}'", fnd.display()),
}
}
ReadbackError::InvalidAdtMatch => write!(f, "Invalid Adt Match"),
ReadbackError::InvalidStrTerm(term) => {
write!(f, "Invalid String Character value '{}'", term.display())
Term::App { tag: tag2, fun, arg } if tag2 == tag => {
write!(f, "{} {}", fun.display_app(tag), arg)
}
_ => write!(f, "{}", self),
})
}
}
impl Tag {
pub fn display_padded(&self) -> impl fmt::Display + '_ {
DisplayFn(move |f| match self {
Tag::Named(name) => write!(f, "#{name} "),
Tag::Numeric(num) => write!(f, "#{num} "),
Tag::Auto => Ok(()),
Tag::Static => Ok(()),
})
}
}
fn var_as_str(nam: &Option<Name>) -> &str {
nam.as_ref().map_or("*", |x| x.as_str())
}

View File

@ -117,7 +117,7 @@ fn run_file() {
// 1 million nodes for the test runtime. Smaller doesn't seem to make it any faster
let (res, info) =
run_book(book, 1 << 20, RunOpts::default(), WarningOpts::deny_all(), CompileOpts::heavy(), None)?;
Ok(format!("{}{}", display_readback_errors(&info.readback_errors), res.display()))
Ok(format!("{}{}", display_readback_errors(&info.readback_errors), res))
})
}
@ -132,7 +132,7 @@ fn run_lazy() {
// 1 million nodes for the test runtime. Smaller doesn't seem to make it any faster
let (res, info) = run_book(book, 1 << 20, run_opts, WarningOpts::deny_all(), desugar_opts, None)?;
Ok(format!("{}{}", display_readback_errors(&info.readback_errors), res.display()))
Ok(format!("{}{}", display_readback_errors(&info.readback_errors), res))
})
}
@ -143,7 +143,7 @@ fn readback_lnet() {
let book = Book::default();
let compat_net = hvmc_to_net(&net, &Default::default());
let (term, errors) = net_to_term(&compat_net, &book, &Labels::default(), false);
Ok(format!("{}{}", display_readback_errors(&errors), term.display()))
Ok(format!("{}{}", display_readback_errors(&errors), term))
})
}
@ -247,6 +247,6 @@ fn run_entrypoint() {
CompileOpts::heavy(),
Some(Name::new("foo")),
)?;
Ok(format!("{}{}", display_readback_errors(&info.readback_errors), res.display()))
Ok(format!("{}{}", display_readback_errors(&info.readback_errors), res))
})
}

View File

@ -3,6 +3,6 @@ source: tests/golden_tests.rs
input_file: tests/golden_tests/readback_lnet/invalid_mat_mat.hvm
---
Readback Warning:
Invalid Numeric Match with 4 occurrences
Invalid Numeric Match (4 occurrences)
λa match match <Invalid> { 0: 3; +: 4 } { 0: <Invalid>; +: <Invalid> }

View File

@ -3,6 +3,6 @@ source: tests/golden_tests.rs
input_file: tests/golden_tests/readback_lnet/invalid_op2_op2.hvm
---
Readback Warning:
Invalid Numeric Operation with 2 occurrences
Invalid Numeric Operation (2 occurrences)
λa (+ (+ <Invalid> 1) (1 <Invalid>))