cl-ast: Overhaul pretty-printing using std::fmt::Write adapters.

Now you don't have to import cl_ast::format::*!!!
This commit is contained in:
John 2024-04-18 20:47:28 -05:00
parent e4f270da17
commit f315fb5af7
6 changed files with 228 additions and 219 deletions

View File

@ -3,57 +3,24 @@ use super::*;
mod display { mod display {
//! Implements [Display] for [AST](super::super) Types //! Implements [Display] for [AST](super::super) Types
use super::*; use super::*;
pub use delimiters::*; use format::{delimiters::*, *};
use std::{ use std::{
borrow::Borrow, borrow::Borrow,
fmt::{Display, Write}, fmt::{Display, Write},
}; };
mod delimiters {
#![allow(dead_code)] fn separate<I: Display, W: Write>(
#[derive(Clone, Copy, Debug)] iterable: impl IntoIterator<Item = I>,
pub struct Delimiters<'t> { sep: &'static str,
pub open: &'t str, ) -> impl FnOnce(W) -> std::fmt::Result {
pub close: &'t str, move |mut f| {
} for (idx, item) in iterable.into_iter().enumerate() {
/// Delimits with braces decorated with spaces `" {n"`, ..., `"\n}"`
pub const SPACED_BRACES: Delimiters = Delimiters { open: " {\n", close: "\n}" };
/// Delimits with braces on separate lines `{\n`, ..., `\n}`
pub const BRACES: Delimiters = Delimiters { open: "{\n", close: "\n}" };
/// Delimits with parentheses on separate lines `{\n`, ..., `\n}`
pub const PARENS: Delimiters = Delimiters { open: "(\n", close: "\n)" };
/// Delimits with square brackets on separate lines `{\n`, ..., `\n}`
pub const SQUARE: Delimiters = Delimiters { open: "[\n", close: "\n]" };
/// Delimits with braces on the same line `{ `, ..., ` }`
pub const INLINE_BRACES: Delimiters = Delimiters { open: "{ ", close: " }" };
/// Delimits with parentheses on the same line `( `, ..., ` )`
pub const INLINE_PARENS: Delimiters = Delimiters { open: "(", close: ")" };
/// Delimits with square brackets on the same line `[ `, ..., ` ]`
pub const INLINE_SQUARE: Delimiters = Delimiters { open: "[", close: "]" };
}
fn delimit<'a>(
func: impl Fn(&mut std::fmt::Formatter<'_>) -> std::fmt::Result + 'a,
delim: Delimiters<'a>,
) -> impl Fn(&mut std::fmt::Formatter<'_>) -> std::fmt::Result + 'a {
move |f| {
write!(f, "{}", delim.open)?;
func(f)?;
write!(f, "{}", delim.close)
}
}
fn separate<'iterable, I>(
iterable: &'iterable [I],
sep: impl Display + 'iterable,
) -> impl Fn(&mut std::fmt::Formatter<'_>) -> std::fmt::Result + 'iterable
where
I: Display,
{
move |f| {
for (idx, item) in iterable.iter().enumerate() {
if idx > 0 { if idx > 0 {
write!(f, "{sep}")?; f.write_str(sep)?;
} }
item.fmt(f)?; write!(f, "{item}")?;
} }
Ok(()) Ok(())
} }
@ -67,6 +34,7 @@ mod display {
} }
} }
} }
impl Display for Visibility { impl Display for Visibility {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self { match self {
@ -76,6 +44,23 @@ mod display {
} }
} }
impl Display for Identifier {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
self.0.fmt(f)
}
}
impl Display for Literal {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Literal::Bool(v) => v.fmt(f),
Literal::Char(v) => write!(f, "'{v}'"),
Literal::Int(v) => v.fmt(f),
Literal::String(v) => write!(f, "\"{v}\""),
}
}
}
impl Display for File { impl Display for File {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
separate(&self.items, "\n\n")(f) separate(&self.items, "\n\n")(f)
@ -89,22 +74,24 @@ mod display {
return Ok(()); return Ok(());
} }
"#".fmt(f)?; "#".fmt(f)?;
delimit(separate(meta, ", "), INLINE_SQUARE)(f)?; separate(meta, ", ")(&mut f.delimit(INLINE_SQUARE))?;
"\n".fmt(f) "\n".fmt(f)
} }
} }
impl Display for Meta { impl Display for Meta {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let Self { name, kind } = self; let Self { name, kind } = self;
write!(f, "{name}{kind}") write!(f, "{name}{kind}")
} }
} }
impl Display for MetaKind { impl Display for MetaKind {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self { match self {
MetaKind::Plain => Ok(()), MetaKind::Plain => Ok(()),
MetaKind::Equals(v) => write!(f, " = {v}"), MetaKind::Equals(v) => write!(f, " = {v}"),
MetaKind::Func(args) => delimit(separate(args, ", "), INLINE_PARENS)(f), MetaKind::Func(args) => separate(args, ", ")(f.delimit(INLINE_PARENS)),
} }
} }
} }
@ -114,7 +101,13 @@ mod display {
let Self { extents: _, attrs, vis, kind } = self; let Self { extents: _, attrs, vis, kind } = self;
attrs.fmt(f)?; attrs.fmt(f)?;
vis.fmt(f)?; vis.fmt(f)?;
match kind { kind.fmt(f)
}
}
impl Display for ItemKind {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
ItemKind::Alias(v) => v.fmt(f), ItemKind::Alias(v) => v.fmt(f),
ItemKind::Const(v) => v.fmt(f), ItemKind::Const(v) => v.fmt(f),
ItemKind::Static(v) => v.fmt(f), ItemKind::Static(v) => v.fmt(f),
@ -126,6 +119,7 @@ mod display {
} }
} }
} }
impl Display for Alias { impl Display for Alias {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let Self { to, from } = self; let Self { to, from } = self;
@ -135,35 +129,40 @@ mod display {
} }
} }
} }
impl Display for Const { impl Display for Const {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let Self { name, ty, init } = self; let Self { name, ty, init } = self;
write!(f, "const {name}: {ty} = {init}") write!(f, "const {name}: {ty} = {init}")
} }
} }
impl Display for Static { impl Display for Static {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let Self { mutable, name, ty, init } = self; let Self { mutable, name, ty, init } = self;
write!(f, "static {mutable}{name}: {ty} = {init}") write!(f, "static {mutable}{name}: {ty} = {init}")
} }
} }
impl Display for Module { impl Display for Module {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let Self { name, kind } = self; let Self { name, kind } = self;
write!(f, "mod {name}{kind}") write!(f, "mod {name}{kind}")
} }
} }
impl Display for ModuleKind { impl Display for ModuleKind {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self { match self {
ModuleKind::Inline(items) => { ModuleKind::Inline(items) => {
' '.fmt(f)?; ' '.fmt(f)?;
delimit(|f| items.fmt(f), BRACES)(f) write!(f.delimit(BRACES), "{items}")
} }
ModuleKind::Outline => ';'.fmt(f), ModuleKind::Outline => ';'.fmt(f),
} }
} }
} }
impl Display for Function { impl Display for Function {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let Self { name, sign: sign @ TyFn { args, rety }, bind, body } = self; let Self { name, sign: sign @ TyFn { args, rety }, bind, body } = self;
@ -178,18 +177,15 @@ mod display {
debug_assert_eq!(bind.len(), types.len()); debug_assert_eq!(bind.len(), types.len());
write!(f, "fn {name} ")?; write!(f, "fn {name} ")?;
delimit( {
|f| { let mut f = f.delimit(INLINE_PARENS);
for (idx, (arg, ty)) in bind.iter().zip(types.iter()).enumerate() { for (idx, (arg, ty)) in bind.iter().zip(types.iter()).enumerate() {
if idx != 0 { if idx != 0 {
f.write_str(", ")?; f.write_str(", ")?;
}
write!(f, "{arg}: {ty}")?;
} }
Ok(()) write!(f, "{arg}: {ty}")?;
}, }
INLINE_PARENS, }
)(f)?;
if let Some(rety) = rety { if let Some(rety) = rety {
write!(f, " -> {rety}")?; write!(f, " -> {rety}")?;
} }
@ -199,70 +195,80 @@ mod display {
} }
} }
} }
impl Display for Param { impl Display for Param {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let Self { mutability, name } = self; let Self { mutability, name } = self;
write!(f, "{mutability}{name}") write!(f, "{mutability}{name}")
} }
} }
impl Display for Struct { impl Display for Struct {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let Self { name, kind } = self; let Self { name, kind } = self;
write!(f, "struct {name}{kind}") write!(f, "struct {name}{kind}")
} }
} }
impl Display for StructKind { impl Display for StructKind {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self { match self {
StructKind::Empty => ';'.fmt(f), StructKind::Empty => ';'.fmt(f),
StructKind::Tuple(v) => delimit(separate(v, ", "), INLINE_PARENS)(f), StructKind::Tuple(v) => separate(v, ", ")(f.delimit(INLINE_PARENS)),
StructKind::Struct(v) => delimit(separate(v, ",\n"), SPACED_BRACES)(f), StructKind::Struct(v) => separate(v, ",\n")(f.delimit(SPACED_BRACES)),
} }
} }
} }
impl Display for StructMember { impl Display for StructMember {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let Self { vis, name, ty } = self; let Self { vis, name, ty } = self;
write!(f, "{vis}{name}: {ty}") write!(f, "{vis}{name}: {ty}")
} }
} }
impl Display for Enum { impl Display for Enum {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let Self { name, kind } = self; let Self { name, kind } = self;
write!(f, "enum {name}{kind}") write!(f, "enum {name}{kind}")
} }
} }
impl Display for EnumKind { impl Display for EnumKind {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self { match self {
EnumKind::NoVariants => ';'.fmt(f), EnumKind::NoVariants => ';'.fmt(f),
EnumKind::Variants(v) => delimit(separate(v, ",\n"), SPACED_BRACES)(f), EnumKind::Variants(v) => separate(v, ",\n")(f.delimit(SPACED_BRACES)),
} }
} }
} }
impl Display for Variant { impl Display for Variant {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let Self { name, kind } = self; let Self { name, kind } = self;
write!(f, "{name}{kind}") write!(f, "{name}{kind}")
} }
} }
impl Display for VariantKind { impl Display for VariantKind {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self { match self {
VariantKind::Plain => Ok(()), VariantKind::Plain => Ok(()),
VariantKind::CLike(n) => write!(f, " = {n}"), VariantKind::CLike(n) => write!(f, " = {n}"),
VariantKind::Tuple(v) => v.fmt(f), VariantKind::Tuple(v) => v.fmt(f),
VariantKind::Struct(v) => delimit(separate(v, ", "), INLINE_BRACES)(f), VariantKind::Struct(v) => separate(v, ", ")(f.delimit(INLINE_BRACES)),
} }
} }
} }
impl Display for Impl { impl Display for Impl {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let Self { target, body } = self; let Self { target, body } = self;
write!(f, "impl {target} ")?; write!(f, "impl {target} ")?;
delimit(|f| body.fmt(f), BRACES)(f) write!(f.delimit(BRACES), "{body}")
} }
} }
impl Display for ImplKind { impl Display for ImplKind {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self { match self {
@ -279,6 +285,7 @@ mod display {
self.kind.fmt(f) self.kind.fmt(f)
} }
} }
impl Display for TyKind { impl Display for TyKind {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self { match self {
@ -292,11 +299,13 @@ mod display {
} }
} }
} }
impl Display for TyTuple { impl Display for TyTuple {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
delimit(separate(&self.types, ", "), INLINE_PARENS)(f) separate(&self.types, ", ")(f.delimit(INLINE_PARENS))
} }
} }
impl Display for TyRef { impl Display for TyRef {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let &Self { count, mutable, ref to } = self; let &Self { count, mutable, ref to } = self;
@ -306,6 +315,7 @@ mod display {
write!(f, "{mutable}{to}") write!(f, "{mutable}{to}")
} }
} }
impl Display for TyFn { impl Display for TyFn {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let Self { args, rety } = self; let Self { args, rety } = self;
@ -317,21 +327,53 @@ mod display {
} }
} }
impl Display for Path {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let Self { absolute, parts } = self;
if *absolute {
"::".fmt(f)?;
}
separate(parts, "::")(f)
}
}
impl Display for PathPart {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
PathPart::SuperKw => "super".fmt(f),
PathPart::SelfKw => "self".fmt(f),
PathPart::Ident(id) => id.fmt(f),
}
}
}
impl Display for Stmt { impl Display for Stmt {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let Stmt { extents: _, kind, semi } = self; let Stmt { extents: _, kind, semi } = self;
match kind { write!(f, "{kind}{semi}")
}
}
impl Display for StmtKind {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
StmtKind::Empty => Ok(()), StmtKind::Empty => Ok(()),
StmtKind::Local(v) => v.fmt(f), StmtKind::Local(v) => v.fmt(f),
StmtKind::Item(v) => v.fmt(f), StmtKind::Item(v) => v.fmt(f),
StmtKind::Expr(v) => v.fmt(f), StmtKind::Expr(v) => v.fmt(f),
}?; }
match semi { }
}
impl Display for Semi {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Semi::Terminated => ';'.fmt(f), Semi::Terminated => ';'.fmt(f),
Semi::Unterminated => Ok(()), Semi::Unterminated => Ok(()),
} }
} }
} }
impl Display for Let { impl Display for Let {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let Self { mutable, name, ty, init } = self; let Self { mutable, name, ty, init } = self;
@ -351,9 +393,11 @@ mod display {
self.kind.fmt(f) self.kind.fmt(f)
} }
} }
impl Display for ExprKind { impl Display for ExprKind {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self { match self {
ExprKind::Empty => "()".fmt(f),
ExprKind::Assign(v) => v.fmt(f), ExprKind::Assign(v) => v.fmt(f),
ExprKind::Binary(v) => v.fmt(f), ExprKind::Binary(v) => v.fmt(f),
ExprKind::Unary(v) => v.fmt(f), ExprKind::Unary(v) => v.fmt(f),
@ -364,7 +408,6 @@ mod display {
ExprKind::ArrayRep(v) => v.fmt(f), ExprKind::ArrayRep(v) => v.fmt(f),
ExprKind::AddrOf(v) => v.fmt(f), ExprKind::AddrOf(v) => v.fmt(f),
ExprKind::Block(v) => v.fmt(f), ExprKind::Block(v) => v.fmt(f),
ExprKind::Empty => "()".fmt(f),
ExprKind::Group(v) => v.fmt(f), ExprKind::Group(v) => v.fmt(f),
ExprKind::Tuple(v) => v.fmt(f), ExprKind::Tuple(v) => v.fmt(f),
ExprKind::Loop(v) => v.fmt(f), ExprKind::Loop(v) => v.fmt(f),
@ -377,12 +420,14 @@ mod display {
} }
} }
} }
impl Display for Assign { impl Display for Assign {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let Self { kind, parts } = self; let Self { kind, parts } = self;
write!(f, "{} {kind} {}", parts.0, parts.1) write!(f, "{} {kind} {}", parts.0, parts.1)
} }
} }
impl Display for AssignKind { impl Display for AssignKind {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self { match self {
@ -401,6 +446,7 @@ mod display {
.fmt(f) .fmt(f)
} }
} }
impl Display for Binary { impl Display for Binary {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let Self { kind, parts } = self; let Self { kind, parts } = self;
@ -412,6 +458,7 @@ mod display {
} }
} }
} }
impl Display for BinaryKind { impl Display for BinaryKind {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self { match self {
@ -442,12 +489,14 @@ mod display {
.fmt(f) .fmt(f)
} }
} }
impl Display for Unary { impl Display for Unary {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let Self { kind, tail } = self; let Self { kind, tail } = self;
write!(f, "{kind}{tail}") write!(f, "{kind}{tail}")
} }
} }
impl Display for UnaryKind { impl Display for UnaryKind {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self { match self {
@ -460,62 +509,28 @@ mod display {
.fmt(f) .fmt(f)
} }
} }
impl Display for Tuple {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
delimit(separate(&self.exprs, ", "), INLINE_PARENS)(f)
}
}
impl Display for Index { impl Display for Index {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let Self { head, indices } = self; let Self { head, indices } = self;
write!(f, "{head}")?; write!(f, "{head}")?;
delimit(separate(indices, ", "), INLINE_SQUARE)(f) separate(indices, ", ")(f.delimit(INLINE_SQUARE))
}
}
impl Display for Path {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let Self { absolute, parts } = self;
if *absolute {
"::".fmt(f)?;
}
separate(parts, "::")(f)
}
}
impl Display for PathPart {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
PathPart::SuperKw => "super".fmt(f),
PathPart::SelfKw => "self".fmt(f),
PathPart::Ident(id) => id.fmt(f),
}
}
}
impl Display for Identifier {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
self.0.fmt(f)
}
}
impl Display for Literal {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Literal::Bool(v) => v.fmt(f),
Literal::Char(v) => write!(f, "'{v}'"),
Literal::Int(v) => v.fmt(f),
Literal::String(v) => write!(f, "\"{v}\""),
}
} }
} }
impl Display for Array { impl Display for Array {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
delimit(separate(&self.values, ", "), INLINE_SQUARE)(f) separate(&self.values, ", ")(f.delimit(INLINE_SQUARE))
} }
} }
impl Display for ArrayRep { impl Display for ArrayRep {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let Self { value, repeat } = self; let Self { value, repeat } = self;
write!(f, "[{value}; {repeat}]") write!(f, "[{value}; {repeat}]")
} }
} }
impl Display for AddrOf { impl Display for AddrOf {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let Self { count, mutable, expr } = self; let Self { count, mutable, expr } = self;
@ -525,40 +540,53 @@ mod display {
write!(f, "{mutable}{expr}") write!(f, "{mutable}{expr}")
} }
} }
impl Display for Block { impl Display for Block {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
delimit(separate(&self.stmts, "\n"), BRACES)(f) separate(&self.stmts, "\n")(f.delimit(BRACES))
} }
} }
impl Display for Group { impl Display for Group {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "({})", self.expr) write!(f, "({})", self.expr)
} }
} }
impl Display for Tuple {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
separate(&self.exprs, ", ")(f.delimit(INLINE_PARENS))
}
}
impl Display for Loop { impl Display for Loop {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let Self { body } = self; let Self { body } = self;
write!(f, "loop {body}") write!(f, "loop {body}")
} }
} }
impl Display for While { impl Display for While {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let Self { cond, pass, fail } = self; let Self { cond, pass, fail } = self;
write!(f, "while {cond} {pass}{fail}") write!(f, "while {cond} {pass}{fail}")
} }
} }
impl Display for If { impl Display for If {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let Self { cond, pass, fail } = self; let Self { cond, pass, fail } = self;
write!(f, "if {cond} {pass}{fail}") write!(f, "if {cond} {pass}{fail}")
} }
} }
impl Display for For { impl Display for For {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let Self { bind, cond, pass, fail } = self; let Self { bind, cond, pass, fail } = self;
write!(f, "for {bind} in {cond} {pass}{fail}") write!(f, "for {bind} in {cond} {pass}{fail}")
} }
} }
impl Display for Else { impl Display for Else {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match &self.body { match &self.body {
@ -567,6 +595,7 @@ mod display {
} }
} }
} }
impl Display for Break { impl Display for Break {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "break")?; write!(f, "break")?;
@ -576,6 +605,7 @@ mod display {
} }
} }
} }
impl Display for Return { impl Display for Return {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "return")?; write!(f, "return")?;
@ -585,6 +615,12 @@ mod display {
} }
} }
} }
impl Display for Continue {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
"continue".fmt(f)
}
}
} }
mod convert { mod convert {

View File

@ -1,106 +1,78 @@
use std::{
fmt::{Result as FmtResult, Write as FmtWrite},
io::{Result as IoResult, Write as IoWrite},
};
/// Trait which adds a function to [fmt Writers](FmtWrite) to turn them into [Prettifier] use delimiters::Delimiters;
pub trait FmtPretty: FmtWrite { use std::fmt::Write;
/// Indents code according to the number of matched curly braces
fn pretty(self) -> Prettifier<'static, Self> impl<W: Write + ?Sized> FmtAdapter for W {}
where Self: Sized { pub trait FmtAdapter: Write {
Prettifier::new(self) fn indent(&mut self) -> Indent<Self> {
Indent { f: self }
} }
} fn delimit(&mut self, delim: Delimiters) -> Delimit<Self> {
/// Trait which adds a function to [io Writers](IoWrite) to turn them into [Prettifier] Delimit::new(self, delim)
pub trait IoPretty: IoWrite {
/// Indents code according to the number of matched curly braces
fn pretty(self) -> Prettifier<'static, Self>
where Self: Sized;
}
impl<W: FmtWrite> FmtPretty for W {}
impl<W: IoWrite> IoPretty for W {
fn pretty(self) -> Prettifier<'static, Self> {
Prettifier::new(self)
} }
} }
/// Intercepts calls to either [std::io::Write] or [std::fmt::Write], /// Pads text with leading indentation after every newline
/// and inserts indentation between matched parentheses pub struct Indent<'f, F: Write + ?Sized> {
pub struct Prettifier<'i, T: ?Sized> { f: &'f mut F,
level: isize,
indent: &'i str,
writer: T,
} }
impl<'i, W> Prettifier<'i, W> { impl<'f, F: Write + ?Sized> Write for Indent<'f, F> {
pub fn new(writer: W) -> Self { fn write_str(&mut self, s: &str) -> std::fmt::Result {
Self { level: 0, indent: " ", writer } for s in s.split_inclusive('\n') {
} self.f.write_str(s)?;
pub fn with_indent(indent: &'i str, writer: W) -> Self { if s.ends_with('\n') {
Self { level: 0, indent, writer } self.f.write_str(" ")?;
}
}
impl<'i, W: FmtWrite> Prettifier<'i, W> {
#[inline]
fn fmt_write_indentation(&mut self) -> FmtResult {
let Self { level, indent, writer } = self;
for _ in 0..*level {
writer.write_str(indent)?;
}
Ok(())
}
}
impl<'i, W: IoWrite> Prettifier<'i, W> {
pub fn io_write_indentation(&mut self) -> IoResult<usize> {
let Self { level, indent, writer } = self;
let mut count = 0;
for _ in 0..*level {
count += writer.write(indent.as_bytes())?;
}
Ok(count)
}
}
impl<'i, W: FmtWrite> FmtWrite for Prettifier<'i, W> {
fn write_str(&mut self, s: &str) -> FmtResult {
for s in s.split_inclusive(['{', '}']) {
match s.as_bytes().last() {
Some(b'{') => self.level += 1,
Some(b'}') => self.level -= 1,
_ => (),
}
for s in s.split_inclusive('\n') {
self.writer.write_str(s)?;
if let Some(b'\n') = s.as_bytes().last() {
self.fmt_write_indentation()?;
}
} }
} }
Ok(()) Ok(())
} }
} }
impl<'i, W: IoWrite> IoWrite for Prettifier<'i, W> { /// Prints [Delimiters] around anything formatted with this. Implies [Indent]
fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> { pub struct Delimit<'f, F: Write + ?Sized> {
let mut size = 0; f: Indent<'f, F>,
for buf in buf.split_inclusive(|b| b"{}".contains(b)) { delim: Delimiters,
match buf.last() { }
Some(b'{') => self.level += 1, impl<'f, F: Write + ?Sized> Delimit<'f, F> {
Some(b'}') => self.level -= 1, pub fn new(f: &'f mut F, delim: Delimiters) -> Self {
_ => (), let mut f = f.indent();
} let _ = f.write_str(delim.open);
for buf in buf.split_inclusive(|b| b'\n' == *b) { Self { f, delim }
size += self.writer.write(buf)?;
if let Some(b'\n') = buf.last() {
self.io_write_indentation()?;
}
}
}
Ok(size)
}
fn flush(&mut self) -> std::io::Result<()> {
self.writer.flush()
} }
} }
impl<'f, F: Write + ?Sized> Drop for Delimit<'f, F> {
fn drop(&mut self) {
let Self { f: Indent { f, .. }, delim } = self;
let _ = f.write_str(delim.close);
}
}
impl<'f, F: Write + ?Sized> Write for Delimit<'f, F> {
fn write_str(&mut self, s: &str) -> std::fmt::Result {
self.f.write_str(s)
}
}
pub mod delimiters {
#![allow(dead_code)]
#[derive(Clone, Copy, Debug)]
pub struct Delimiters {
pub open: &'static str,
pub close: &'static str,
}
/// Delimits with braces decorated with spaces `" {n"`, ..., `"\n}"`
pub const SPACED_BRACES: Delimiters = Delimiters { open: " {\n", close: "\n}" };
/// Delimits with braces on separate lines `{\n`, ..., `\n}`
pub const BRACES: Delimiters = Delimiters { open: "{\n", close: "\n}" };
/// Delimits with parentheses on separate lines `{\n`, ..., `\n}`
pub const PARENS: Delimiters = Delimiters { open: "(\n", close: "\n)" };
/// Delimits with square brackets on separate lines `{\n`, ..., `\n}`
pub const SQUARE: Delimiters = Delimiters { open: "[\n", close: "\n]" };
/// Delimits with braces on the same line `{ `, ..., ` }`
pub const INLINE_BRACES: Delimiters = Delimiters { open: "{ ", close: " }" };
/// Delimits with parentheses on the same line `( `, ..., ` )`
pub const INLINE_PARENS: Delimiters = Delimiters { open: "(", close: ")" };
/// Delimits with square brackets on the same line `[ `, ..., ` ]`
pub const INLINE_SQUARE: Delimiters = Delimiters { open: "[", close: "]" };
}

View File

@ -282,9 +282,7 @@ pub mod temp_type_impl {
')'.fmt(f) ')'.fmt(f)
} }
ConValue::Function(func) => { ConValue::Function(func) => {
use cl_ast::format::*; write!(f, "{}", func.decl())
use std::fmt::Write;
write!(f.pretty(), "{}", func.decl())
} }
ConValue::BuiltIn(func) => { ConValue::BuiltIn(func) => {
write!(f, "{}", func.description()) write!(f, "{}", func.description())

View File

@ -12,6 +12,7 @@ const STDLIB: &str = include_str!("../../stdlib/lib.cl");
const C_MAIN: &str = "\x1b[30m"; const C_MAIN: &str = "\x1b[30m";
const C_RESV: &str = "\x1b[35m"; const C_RESV: &str = "\x1b[35m";
const C_CODE: &str = "\x1b[36m"; const C_CODE: &str = "\x1b[36m";
const C_LISTING: &str = "\x1b[38;5;117m";
/// A home for immutable intermediate ASTs /// A home for immutable intermediate ASTs
/// ///
@ -144,12 +145,15 @@ fn list_types(prj: &mut Project) -> Result<(), Box<dyn Error>> {
fn pretty_def(def: &Def, id: impl Into<usize>) { fn pretty_def(def: &Def, id: impl Into<usize>) {
let id = id.into(); let id = id.into();
let Def { vis, name, kind, module, meta, source: _ } = def; let Def { vis, name, kind, module, meta, source } = def;
for meta in *meta { for meta in *meta {
println!("#[{meta}]") println!("#[{meta}]")
} }
println!("{vis}{name} [id: {id}] = {kind}"); println!("{vis}{name} [id: {id}] = {kind}");
println!("Module:\n\x1b[97m{module}\x1b[0m"); if let Some(source) = source {
println!("Source:\n{C_LISTING}{source}\x1b[0m");
}
println!("\x1b[90m{module}\x1b[0m");
} }
fn clear() -> Result<(), Box<dyn Error>> { fn clear() -> Result<(), Box<dyn Error>> {

View File

@ -85,11 +85,11 @@ pub mod program {
env::Environment, error::IResult, interpret::Interpret, temp_type_impl::ConValue, env::Environment, error::IResult, interpret::Interpret, temp_type_impl::ConValue,
}; };
use cl_ast::{self as ast, format::*}; use cl_ast as ast;
use cl_lexer::Lexer; use cl_lexer::Lexer;
use cl_parser::{error::PResult, Parser}; use cl_parser::{error::PResult, Parser};
// use conlang::resolver::{error::TyResult, Resolver}; // use conlang::resolver::{error::TyResult, Resolver};
use std::{fmt::Display, io::Write}; use std::fmt::Display;
pub struct Parsable; pub struct Parsable;
@ -136,13 +136,11 @@ pub mod program {
} }
} }
pub fn print(&self) { pub fn print(&self) {
let mut f = std::io::stdout().pretty(); match &self.data {
let _ = match &self.data { Parsed::File(v) => println!("{v}"),
Parsed::File(v) => writeln!(f, "{v}"), Parsed::Stmt(v) => println!("{v}"),
Parsed::Stmt(v) => writeln!(f, "{v}"), Parsed::Expr(v) => println!("{v}"),
Parsed::Expr(v) => writeln!(f, "{v}"),
}; };
// println!("{self}")
} }
pub fn run(&self, env: &mut Environment) -> IResult<ConValue> { pub fn run(&self, env: &mut Environment) -> IResult<ConValue> {

View File

@ -1,7 +1,7 @@
//! [Display] implementations for [TypeKind], [Adt], and [Intrinsic] //! [Display] implementations for [TypeKind], [Adt], and [Intrinsic]
use super::{Adt, Def, DefKind, Intrinsic, TypeKind, ValueKind}; use super::{Adt, Def, DefKind, Intrinsic, TypeKind, ValueKind};
use cl_ast::format::FmtPretty; use cl_ast::format::FmtAdapter;
use std::{ use std::{
fmt::{self, Display, Write}, fmt::{self, Display, Write},
iter, iter,
@ -31,13 +31,14 @@ where
impl Display for Def<'_> { impl Display for Def<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let Self { name, vis, meta, kind, source, module } = self; let Self { name, vis, meta, kind, source, module } = self;
if !meta.is_empty() {
writeln!(f, "#{meta:?}")?;
}
writeln!(f, "{vis}{name}: ")?; writeln!(f, "{vis}{name}: ")?;
writeln!(f, "kind: {kind}")?; writeln!(f, "kind: {kind}")?;
if !meta.is_empty() {
writeln!(f, "meta: {meta:?}")?;
}
if let Some(source) = source { if let Some(source) = source {
writeln!(f.pretty(), "source: {{\n{source}\n}}")?; writeln!(f, "source:")?;
writeln!(f.indent(), "\n{source}")?;
} }
write!(f, "module: {module}") write!(f, "module: {module}")
} }