use super::{
NUMBER_COLOR, PrettySimple, STRING_CONTENT_COLOR, STRING_QUOTE_COLOR, Writer, escape_string,
format_bracket_list, sub_expr, with_brackets,
};
use crate::format_constructor;
use crate::format_enum;
use crate::format_record;
use crate::types::{
Ann, Binder, Expression, Item, ParamAttr, ParamDefault, Parameter, Selector, SetDefault,
SimpleSelector, Span, StringPart, Term, Token, TrailingComment, Trivia, Trivium, Whole,
};
macro_rules! simple_atom {
($ty:ty, |$self_:ident, $w:ident| $body:expr) => {
impl PrettySimple for $ty {
fn format<W: Writer>(&self, $w: &mut W) {
let $self_ = self;
$body
}
fn is_simple(&self) -> bool {
true
}
fn is_atomic(&self) -> bool {
true
}
}
};
}
simple_atom!(&str, |s, w| {
w.write_colored("\"", STRING_QUOTE_COLOR);
w.write_colored(&escape_string(s), STRING_CONTENT_COLOR);
w.write_colored("\"", STRING_QUOTE_COLOR);
});
simple_atom!(String, |s, w| s.as_str().format(w));
simple_atom!(Box<str>, |s, w| (&**s).format(w));
simple_atom!(isize, |n, w| w.write_colored(&n.to_string(), NUMBER_COLOR));
simple_atom!(usize, |n, w| w.write_colored(&n.to_string(), NUMBER_COLOR));
simple_atom!(bool, |b, w| w.write_plain(if *b {
"True"
} else {
"False"
}));
impl PrettySimple for Whole<Expression> {
fn format<W: Writer>(&self, w: &mut W) {
self.value.format(w);
w.newline(); }
}
impl PrettySimple for Expression {
fn format<W: Writer>(&self, w: &mut W) {
match self {
Self::Term(term) => format_constructor!(w, "Term", [term]),
Self::With {
kw_with,
scope,
semi,
body,
} => {
format_constructor!(w, "With", [kw_with, &**scope, semi, &**body]);
}
Self::Let {
kw_let,
bindings,
kw_in,
body,
} => {
format_constructor!(w, "Let", [kw_let, &bindings.0, kw_in, &**body]);
}
Self::Assert {
kw_assert,
cond,
semi,
body,
} => {
format_constructor!(w, "Assert", [kw_assert, &**cond, semi, &**body]);
}
Self::If {
kw_if,
cond,
kw_then,
then_branch,
kw_else,
else_branch,
} => {
format_constructor!(
w,
"If",
[
kw_if,
&**cond,
kw_then,
&**then_branch,
kw_else,
&**else_branch
]
);
}
Self::Abstraction { param, colon, body } => {
format_constructor!(w, "Abstraction", [param, colon, &**body]);
}
Self::Application { func, arg } => {
format_constructor!(w, "Application", [&**func, &**arg]);
}
Self::Operation { lhs, op, rhs } => {
format_constructor!(w, "Operation", [&**lhs, op, &**rhs]);
}
Self::MemberCheck {
lhs,
question,
path,
} => {
format_constructor!(w, "MemberCheck", [&**lhs, question, path]);
}
Self::Negation { minus, expr } => {
format_constructor!(w, "Negation", [minus, &**expr]);
}
Self::Inversion { bang, expr } => {
format_constructor!(w, "Inversion", [bang, &**expr]);
}
}
}
}
impl PrettySimple for Term {
fn format<W: Writer>(&self, w: &mut W) {
match self {
Self::Token(leaf) => format_constructor!(w, "Token", [leaf]),
Self::SimpleString(s) => format_constructor!(w, "SimpleString", [s]),
Self::IndentedString(s) => format_constructor!(w, "IndentedString", [s]),
Self::Path(p) => format_constructor!(w, "Path", [p]),
Self::List { open, items, close } => {
format_constructor!(w, "List", [open, &items.0, close]);
}
Self::Set {
rec,
open,
items,
close,
} => {
format_constructor!(w, "Set", [rec, open, &items.0, close]);
}
Self::Selection {
base,
selectors,
default,
} => {
format_constructor!(w, "Selection", [&**base, selectors, default]);
}
Self::Parenthesized { open, expr, close } => {
format_constructor!(w, "Parenthesized", [open, &**expr, close]);
}
}
}
}
fn format_pair<W: Writer, A: PrettySimple, B: PrettySimple>(w: &mut W, a: &A, b: &B) {
with_brackets(w, "(", ")", true, |w, paren_color| {
w.write_plain(" ");
a.format(w);
w.newline();
w.write_colored(",", paren_color);
w.write_plain(" ");
b.format(w);
w.newline();
});
}
impl PrettySimple for SetDefault {
fn format<W: Writer>(&self, w: &mut W) {
format_pair(w, &self.or_kw, &*self.value);
}
fn has_delimiters(&self) -> bool {
true
}
}
impl PrettySimple for ParamDefault {
fn format<W: Writer>(&self, w: &mut W) {
format_pair(w, &self.question, &self.value);
}
fn has_delimiters(&self) -> bool {
true
}
}
impl<T: PrettySimple> PrettySimple for Item<T> {
fn format<W: Writer>(&self, w: &mut W) {
match self {
Self::Item(inner) => {
format_constructor!(w, "Item", [inner]);
}
Self::Comments(trivia) => {
w.write_plain("Comments");
sub_expr(w, trivia);
}
}
}
fn is_simple(&self) -> bool {
match self {
Self::Item(_) => false,
Self::Comments(trivia) => trivia.is_simple(),
}
}
}
impl PrettySimple for Binder {
fn format<W: Writer>(&self, w: &mut W) {
match self {
Self::Inherit {
kw,
from,
attrs,
semi,
} => {
format_constructor!(w, "Inherit", [kw, from, attrs, semi]);
}
Self::Assignment {
path,
eq,
value,
semi,
} => {
format_constructor!(w, "Assignment", [path, eq, value, semi]);
}
}
}
}
impl PrettySimple for Selector {
fn format<W: Writer>(&self, w: &mut W) {
format_constructor!(w, "Selector", [&self.dot, &self.selector]);
}
}
impl PrettySimple for SimpleSelector {
fn format<W: Writer>(&self, w: &mut W) {
match self {
Self::ID(leaf) => {
format_constructor!(w, "IDSelector", [leaf]);
}
Self::Interpol(part) => {
format_constructor!(w, "InterpolSelector", [part]);
}
Self::String(string) => {
format_constructor!(w, "StringSelector", [string]);
}
}
}
}
impl PrettySimple for Trivium {
fn format<W: Writer>(&self, w: &mut W) {
format_enum!(self, w, {
EmptyLine() => [],
LineComment(text) => [text],
BlockComment(is_doc, lines) => [is_doc, lines],
LanguageAnnotation(text) => [text],
});
}
fn is_simple(&self) -> bool {
match self {
Self::EmptyLine() | Self::LineComment(_) | Self::LanguageAnnotation(_) => true,
Self::BlockComment(_is_doc, lines) => lines.is_simple(),
}
}
fn is_atomic(&self) -> bool {
matches!(self, Self::EmptyLine())
}
}
impl PrettySimple for Trivia {
fn format<W: Writer>(&self, w: &mut W) {
w.write_plain("fromList");
sub_expr(w, &self.to_vec());
}
fn renders_inline_parens(&self) -> bool {
self.to_vec().is_simple()
}
}
impl PrettySimple for Parameter {
fn format<W: Writer>(&self, w: &mut W) {
match self {
Self::Id(leaf) => {
format_constructor!(w, "IDParameter", [leaf]);
}
Self::Set { open, attrs, close } => {
format_constructor!(w, "SetParameter", [open, attrs, close]);
}
Self::Context { lhs, at, rhs } => {
format_constructor!(w, "ContextParameter", [&**lhs, at, &**rhs]);
}
}
}
}
impl PrettySimple for ParamAttr {
fn format<W: Writer>(&self, w: &mut W) {
match self {
Self::Attr {
name,
default,
comma,
} => {
format_constructor!(w, "ParamAttr", [name, default, comma]);
}
Self::Ellipsis(ellipsis) => {
format_constructor!(w, "ParamEllipsis", [ellipsis]);
}
}
}
}
impl PrettySimple for StringPart {
fn format<W: Writer>(&self, w: &mut W) {
match self {
Self::TextPart(text) => {
format_constructor!(w, "TextPart", [text]);
}
Self::Interpolation(whole) => {
w.write_plain("Interpolation");
w.write_plain(" ");
whole.value.format(w);
}
}
}
fn is_simple(&self) -> bool {
match self {
Self::TextPart(_) => true,
Self::Interpolation(_) => false,
}
}
}
impl PrettySimple for Token {
fn format<W: Writer>(&self, w: &mut W) {
format_enum!(self, w, {
Integer(s) => [&s.as_str()],
Float(s) => [&s.as_str()],
Identifier(s) => [&s.as_str()],
EnvPath(s) => [&s.as_str()],
_ => {
w.write_plain(&format!("{self:?}"));
}
});
}
fn is_simple(&self) -> bool {
true
}
}
#[derive(Debug)]
struct SpanWrapper(Span);
impl PrettySimple for SpanWrapper {
fn format<W: Writer>(&self, w: &mut W) {
use crate::error::context::ErrorContext;
w.write_plain("Pos ");
let ctx = ErrorContext::new(w.source(), None);
let pos = ctx.position(self.0.start());
pos.line.format(w);
}
fn is_simple(&self) -> bool {
true
}
}
impl PrettySimple for TrailingComment {
fn format<W: Writer>(&self, w: &mut W) {
with_brackets(w, "(", ")", true, |w, _| {
w.write_plain(" ");
format_constructor!(w, "TrailingComment", [&&*self.0]);
w.write_plain(" ");
});
}
fn has_delimiters(&self) -> bool {
true
}
}
impl<T: PrettySimple> PrettySimple for Ann<T> {
fn format<W: Writer>(&self, w: &mut W) {
w.write_plain("Ann");
format_record!(
w,
[
("preTrivia", &self.pre_trivia),
("sourceLine", &SpanWrapper(self.span)),
("value", &self.value),
("trailComment", &self.trail_comment),
]
);
}
}
impl<T: PrettySimple> PrettySimple for Vec<T> {
fn format<W: Writer>(&self, w: &mut W) {
format_bracket_list(w, self, true);
}
fn is_simple(&self) -> bool {
if self.is_empty() {
return true;
}
if self.len() == 1 {
let item = &self[0];
return item.is_atomic() || (item.is_simple() && item.has_delimiters());
}
false
}
fn has_delimiters(&self) -> bool {
true
}
fn is_empty(&self) -> bool {
<Self>::is_empty(self)
}
}
impl<T: PrettySimple> PrettySimple for Option<T> {
fn format<W: Writer>(&self, w: &mut W) {
match self {
Some(value) => {
format_constructor!(w, "Just", [value]);
}
None => {
w.write_plain("Nothing");
}
}
}
fn is_simple(&self) -> bool {
self.is_none()
}
}
impl<A: PrettySimple, B: PrettySimple> PrettySimple for (A, B) {
fn format<W: Writer>(&self, w: &mut W) {
with_brackets(w, "(", ")", true, |w, paren_color| {
w.write_plain(" ");
self.0.format(w);
w.newline();
w.write_colored(",", paren_color);
w.write_plain(" ");
self.1.format(w);
w.newline();
});
}
fn has_delimiters(&self) -> bool {
true
}
}
impl<T: PrettySimple> PrettySimple for Box<[T]> {
fn format<W: Writer>(&self, w: &mut W) {
format_bracket_list(w, self, true);
}
fn is_simple(&self) -> bool {
if self.is_empty() {
return true;
}
if self.len() == 1 {
let item = &self[0];
return item.is_atomic() || (item.is_simple() && item.has_delimiters());
}
false
}
fn has_delimiters(&self) -> bool {
true
}
fn is_empty(&self) -> bool {
<[T]>::is_empty(self)
}
}
impl<T: PrettySimple> PrettySimple for Box<T> {
fn format<W: Writer>(&self, w: &mut W) {
(**self).format(w);
}
fn is_simple(&self) -> bool {
(**self).is_simple()
}
}