mirror of
https://github.com/HigherOrderCO/Bend.git
synced 2024-11-05 04:51:40 +03:00
[sc-437] Implement fmt::Display for more things
This commit is contained in:
parent
25a6926ab1
commit
daf34d3784
@ -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,)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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())
|
||||
}
|
||||
|
@ -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))
|
||||
})
|
||||
}
|
||||
|
@ -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> }
|
||||
|
@ -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>))
|
||||
|
Loading…
Reference in New Issue
Block a user