use std::ops::Deref;
use crate::ast::{self, span::Span};
use ast::visitors::dyn_compatible;
use pretty::Pretty;
pub mod pretty_ast;
pub use pretty_ast::PrettyAst;
pub mod render_view;
#[macro_export]
macro_rules! impl_doc_allocator_for {
($ty:ty) => {
impl<'a, A: 'a> ::pretty::DocAllocator<'a, A> for $ty {
type Doc = pretty::BoxDoc<'a, A>;
fn alloc(&'a self, doc: ::pretty::Doc<'a, Self::Doc, A>) -> Self::Doc {
pretty::BoxAllocator.alloc(doc)
}
fn alloc_column_fn(
&'a self,
f: impl Fn(usize) -> Self::Doc + 'a,
) -> <Self::Doc as ::pretty::DocPtr<'a, A>>::ColumnFn {
pretty::BoxAllocator.alloc_column_fn(f)
}
fn alloc_width_fn(
&'a self,
f: impl Fn(isize) -> Self::Doc + 'a,
) -> <Self::Doc as ::pretty::DocPtr<'a, A>>::WidthFn {
pretty::BoxAllocator.alloc_width_fn(f)
}
}
};
}
pub use impl_doc_allocator_for;
pub trait Resugaring: for<'a> dyn_compatible::AstVisitorMut<'a> {
fn name(&self) -> String;
}
pub trait Printer: Sized + for<'a, 'b> PrettyAst<'a, 'b, Span> + Default {
fn resugaring_phases() -> Vec<Box<dyn Resugaring>>;
const NAME: &'static str = <Self as PrettyAst<'static, 'static, Span>>::NAME;
}
pub struct SourceMap;
pub trait Print<T>: Printer {
fn print(&self, mut fragment: T) -> (String, SourceMap)
where
for<'a, 'b> &'b T: Pretty<'a, Self, Span>,
for<'a> dyn Resugaring: dyn_compatible::AstVisitableMut<'a, T>,
{
for mut reguaring_phase in Self::resugaring_phases() {
reguaring_phase.visit(&mut fragment)
}
let doc_builder = fragment.pretty(self).into_doc();
(doc_builder.deref().pretty(80).to_string(), SourceMap)
}
}
impl<P: Printer, T> Print<T> for P {}