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:
parent
e4f270da17
commit
f315fb5af7
@ -3,57 +3,24 @@ use super::*;
|
||||
|
||||
mod display {
|
||||
//! Implements [Display] for [AST](super::super) Types
|
||||
|
||||
use super::*;
|
||||
pub use delimiters::*;
|
||||
use format::{delimiters::*, *};
|
||||
use std::{
|
||||
borrow::Borrow,
|
||||
fmt::{Display, Write},
|
||||
};
|
||||
mod delimiters {
|
||||
#![allow(dead_code)]
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub struct Delimiters<'t> {
|
||||
pub open: &'t str,
|
||||
pub close: &'t 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: "]" };
|
||||
}
|
||||
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() {
|
||||
|
||||
fn separate<I: Display, W: Write>(
|
||||
iterable: impl IntoIterator<Item = I>,
|
||||
sep: &'static str,
|
||||
) -> impl FnOnce(W) -> std::fmt::Result {
|
||||
move |mut f| {
|
||||
for (idx, item) in iterable.into_iter().enumerate() {
|
||||
if idx > 0 {
|
||||
write!(f, "{sep}")?;
|
||||
f.write_str(sep)?;
|
||||
}
|
||||
item.fmt(f)?;
|
||||
write!(f, "{item}")?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
@ -67,6 +34,7 @@ mod display {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for Visibility {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
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 {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
separate(&self.items, "\n\n")(f)
|
||||
@ -89,22 +74,24 @@ mod display {
|
||||
return Ok(());
|
||||
}
|
||||
"#".fmt(f)?;
|
||||
delimit(separate(meta, ", "), INLINE_SQUARE)(f)?;
|
||||
separate(meta, ", ")(&mut f.delimit(INLINE_SQUARE))?;
|
||||
"\n".fmt(f)
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for Meta {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
let Self { name, kind } = self;
|
||||
write!(f, "{name}{kind}")
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for MetaKind {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
MetaKind::Plain => Ok(()),
|
||||
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;
|
||||
attrs.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::Const(v) => v.fmt(f),
|
||||
ItemKind::Static(v) => v.fmt(f),
|
||||
@ -126,6 +119,7 @@ mod display {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for Alias {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
let Self { to, from } = self;
|
||||
@ -135,35 +129,40 @@ mod display {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for Const {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
let Self { name, ty, init } = self;
|
||||
write!(f, "const {name}: {ty} = {init}")
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for Static {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
let Self { mutable, name, ty, init } = self;
|
||||
write!(f, "static {mutable}{name}: {ty} = {init}")
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for Module {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
let Self { name, kind } = self;
|
||||
write!(f, "mod {name}{kind}")
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for ModuleKind {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
ModuleKind::Inline(items) => {
|
||||
' '.fmt(f)?;
|
||||
delimit(|f| items.fmt(f), BRACES)(f)
|
||||
write!(f.delimit(BRACES), "{items}")
|
||||
}
|
||||
ModuleKind::Outline => ';'.fmt(f),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for Function {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
let Self { name, sign: sign @ TyFn { args, rety }, bind, body } = self;
|
||||
@ -178,18 +177,15 @@ mod display {
|
||||
|
||||
debug_assert_eq!(bind.len(), types.len());
|
||||
write!(f, "fn {name} ")?;
|
||||
delimit(
|
||||
|f| {
|
||||
{
|
||||
let mut f = f.delimit(INLINE_PARENS);
|
||||
for (idx, (arg, ty)) in bind.iter().zip(types.iter()).enumerate() {
|
||||
if idx != 0 {
|
||||
f.write_str(", ")?;
|
||||
}
|
||||
write!(f, "{arg}: {ty}")?;
|
||||
}
|
||||
Ok(())
|
||||
},
|
||||
INLINE_PARENS,
|
||||
)(f)?;
|
||||
}
|
||||
if let Some(rety) = rety {
|
||||
write!(f, " -> {rety}")?;
|
||||
}
|
||||
@ -199,70 +195,80 @@ mod display {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for Param {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
let Self { mutability, name } = self;
|
||||
write!(f, "{mutability}{name}")
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for Struct {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
let Self { name, kind } = self;
|
||||
write!(f, "struct {name}{kind}")
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for StructKind {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
StructKind::Empty => ';'.fmt(f),
|
||||
StructKind::Tuple(v) => delimit(separate(v, ", "), INLINE_PARENS)(f),
|
||||
StructKind::Struct(v) => delimit(separate(v, ",\n"), SPACED_BRACES)(f),
|
||||
StructKind::Tuple(v) => separate(v, ", ")(f.delimit(INLINE_PARENS)),
|
||||
StructKind::Struct(v) => separate(v, ",\n")(f.delimit(SPACED_BRACES)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for StructMember {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
let Self { vis, name, ty } = self;
|
||||
write!(f, "{vis}{name}: {ty}")
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for Enum {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
let Self { name, kind } = self;
|
||||
write!(f, "enum {name}{kind}")
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for EnumKind {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
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 {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
let Self { name, kind } = self;
|
||||
write!(f, "{name}{kind}")
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for VariantKind {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
VariantKind::Plain => Ok(()),
|
||||
VariantKind::CLike(n) => write!(f, " = {n}"),
|
||||
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 {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
let Self { target, body } = self;
|
||||
write!(f, "impl {target} ")?;
|
||||
delimit(|f| body.fmt(f), BRACES)(f)
|
||||
write!(f.delimit(BRACES), "{body}")
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for ImplKind {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
@ -279,6 +285,7 @@ mod display {
|
||||
self.kind.fmt(f)
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for TyKind {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
@ -292,11 +299,13 @@ mod display {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for TyTuple {
|
||||
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 {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
let &Self { count, mutable, ref to } = self;
|
||||
@ -306,6 +315,7 @@ mod display {
|
||||
write!(f, "{mutable}{to}")
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for TyFn {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
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 {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
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::Local(v) => v.fmt(f),
|
||||
StmtKind::Item(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::Unterminated => Ok(()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for Let {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
let Self { mutable, name, ty, init } = self;
|
||||
@ -351,9 +393,11 @@ mod display {
|
||||
self.kind.fmt(f)
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for ExprKind {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
ExprKind::Empty => "()".fmt(f),
|
||||
ExprKind::Assign(v) => v.fmt(f),
|
||||
ExprKind::Binary(v) => v.fmt(f),
|
||||
ExprKind::Unary(v) => v.fmt(f),
|
||||
@ -364,7 +408,6 @@ mod display {
|
||||
ExprKind::ArrayRep(v) => v.fmt(f),
|
||||
ExprKind::AddrOf(v) => v.fmt(f),
|
||||
ExprKind::Block(v) => v.fmt(f),
|
||||
ExprKind::Empty => "()".fmt(f),
|
||||
ExprKind::Group(v) => v.fmt(f),
|
||||
ExprKind::Tuple(v) => v.fmt(f),
|
||||
ExprKind::Loop(v) => v.fmt(f),
|
||||
@ -377,12 +420,14 @@ mod display {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for Assign {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
let Self { kind, parts } = self;
|
||||
write!(f, "{} {kind} {}", parts.0, parts.1)
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for AssignKind {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
@ -401,6 +446,7 @@ mod display {
|
||||
.fmt(f)
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for Binary {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
let Self { kind, parts } = self;
|
||||
@ -412,6 +458,7 @@ mod display {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for BinaryKind {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
@ -442,12 +489,14 @@ mod display {
|
||||
.fmt(f)
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for Unary {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
let Self { kind, tail } = self;
|
||||
write!(f, "{kind}{tail}")
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for UnaryKind {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
@ -460,62 +509,28 @@ mod display {
|
||||
.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 {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
let Self { head, indices } = self;
|
||||
write!(f, "{head}")?;
|
||||
delimit(separate(indices, ", "), INLINE_SQUARE)(f)
|
||||
}
|
||||
}
|
||||
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}\""),
|
||||
}
|
||||
separate(indices, ", ")(f.delimit(INLINE_SQUARE))
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for Array {
|
||||
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 {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
let Self { value, repeat } = self;
|
||||
write!(f, "[{value}; {repeat}]")
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for AddrOf {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
let Self { count, mutable, expr } = self;
|
||||
@ -525,40 +540,53 @@ mod display {
|
||||
write!(f, "{mutable}{expr}")
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for Block {
|
||||
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 {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
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 {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
let Self { body } = self;
|
||||
write!(f, "loop {body}")
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for While {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
let Self { cond, pass, fail } = self;
|
||||
write!(f, "while {cond} {pass}{fail}")
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for If {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
let Self { cond, pass, fail } = self;
|
||||
write!(f, "if {cond} {pass}{fail}")
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for For {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
let Self { bind, cond, pass, fail } = self;
|
||||
write!(f, "for {bind} in {cond} {pass}{fail}")
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for Else {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match &self.body {
|
||||
@ -567,6 +595,7 @@ mod display {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for Break {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "break")?;
|
||||
@ -576,6 +605,7 @@ mod display {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for Return {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
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 {
|
||||
|
@ -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]
|
||||
pub trait FmtPretty: FmtWrite {
|
||||
/// Indents code according to the number of matched curly braces
|
||||
fn pretty(self) -> Prettifier<'static, Self>
|
||||
where Self: Sized {
|
||||
Prettifier::new(self)
|
||||
use delimiters::Delimiters;
|
||||
use std::fmt::Write;
|
||||
|
||||
impl<W: Write + ?Sized> FmtAdapter for W {}
|
||||
pub trait FmtAdapter: Write {
|
||||
fn indent(&mut self) -> Indent<Self> {
|
||||
Indent { f: self }
|
||||
}
|
||||
}
|
||||
/// Trait which adds a function to [io Writers](IoWrite) to turn them into [Prettifier]
|
||||
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)
|
||||
fn delimit(&mut self, delim: Delimiters) -> Delimit<Self> {
|
||||
Delimit::new(self, delim)
|
||||
}
|
||||
}
|
||||
|
||||
/// Intercepts calls to either [std::io::Write] or [std::fmt::Write],
|
||||
/// and inserts indentation between matched parentheses
|
||||
pub struct Prettifier<'i, T: ?Sized> {
|
||||
level: isize,
|
||||
indent: &'i str,
|
||||
writer: T,
|
||||
/// Pads text with leading indentation after every newline
|
||||
pub struct Indent<'f, F: Write + ?Sized> {
|
||||
f: &'f mut F,
|
||||
}
|
||||
|
||||
impl<'i, W> Prettifier<'i, W> {
|
||||
pub fn new(writer: W) -> Self {
|
||||
Self { level: 0, indent: " ", writer }
|
||||
}
|
||||
pub fn with_indent(indent: &'i str, writer: W) -> Self {
|
||||
Self { level: 0, indent, writer }
|
||||
}
|
||||
}
|
||||
|
||||
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,
|
||||
_ => (),
|
||||
}
|
||||
impl<'f, F: Write + ?Sized> Write for Indent<'f, F> {
|
||||
fn write_str(&mut self, s: &str) -> std::fmt::Result {
|
||||
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()?;
|
||||
}
|
||||
self.f.write_str(s)?;
|
||||
if s.ends_with('\n') {
|
||||
self.f.write_str(" ")?;
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'i, W: IoWrite> IoWrite for Prettifier<'i, W> {
|
||||
fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
|
||||
let mut size = 0;
|
||||
for buf in buf.split_inclusive(|b| b"{}".contains(b)) {
|
||||
match buf.last() {
|
||||
Some(b'{') => self.level += 1,
|
||||
Some(b'}') => self.level -= 1,
|
||||
_ => (),
|
||||
}
|
||||
for buf in buf.split_inclusive(|b| b'\n' == *b) {
|
||||
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()
|
||||
/// Prints [Delimiters] around anything formatted with this. Implies [Indent]
|
||||
pub struct Delimit<'f, F: Write + ?Sized> {
|
||||
f: Indent<'f, F>,
|
||||
delim: Delimiters,
|
||||
}
|
||||
impl<'f, F: Write + ?Sized> Delimit<'f, F> {
|
||||
pub fn new(f: &'f mut F, delim: Delimiters) -> Self {
|
||||
let mut f = f.indent();
|
||||
let _ = f.write_str(delim.open);
|
||||
Self { f, delim }
|
||||
}
|
||||
}
|
||||
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: "]" };
|
||||
}
|
||||
|
@ -282,9 +282,7 @@ pub mod temp_type_impl {
|
||||
')'.fmt(f)
|
||||
}
|
||||
ConValue::Function(func) => {
|
||||
use cl_ast::format::*;
|
||||
use std::fmt::Write;
|
||||
write!(f.pretty(), "{}", func.decl())
|
||||
write!(f, "{}", func.decl())
|
||||
}
|
||||
ConValue::BuiltIn(func) => {
|
||||
write!(f, "{}", func.description())
|
||||
|
@ -12,6 +12,7 @@ const STDLIB: &str = include_str!("../../stdlib/lib.cl");
|
||||
const C_MAIN: &str = "\x1b[30m";
|
||||
const C_RESV: &str = "\x1b[35m";
|
||||
const C_CODE: &str = "\x1b[36m";
|
||||
const C_LISTING: &str = "\x1b[38;5;117m";
|
||||
|
||||
/// 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>) {
|
||||
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 {
|
||||
println!("#[{meta}]")
|
||||
}
|
||||
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>> {
|
||||
|
@ -85,11 +85,11 @@ pub mod program {
|
||||
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_parser::{error::PResult, Parser};
|
||||
// use conlang::resolver::{error::TyResult, Resolver};
|
||||
use std::{fmt::Display, io::Write};
|
||||
use std::fmt::Display;
|
||||
|
||||
pub struct Parsable;
|
||||
|
||||
@ -136,13 +136,11 @@ pub mod program {
|
||||
}
|
||||
}
|
||||
pub fn print(&self) {
|
||||
let mut f = std::io::stdout().pretty();
|
||||
let _ = match &self.data {
|
||||
Parsed::File(v) => writeln!(f, "{v}"),
|
||||
Parsed::Stmt(v) => writeln!(f, "{v}"),
|
||||
Parsed::Expr(v) => writeln!(f, "{v}"),
|
||||
match &self.data {
|
||||
Parsed::File(v) => println!("{v}"),
|
||||
Parsed::Stmt(v) => println!("{v}"),
|
||||
Parsed::Expr(v) => println!("{v}"),
|
||||
};
|
||||
// println!("{self}")
|
||||
}
|
||||
|
||||
pub fn run(&self, env: &mut Environment) -> IResult<ConValue> {
|
||||
|
@ -1,7 +1,7 @@
|
||||
//! [Display] implementations for [TypeKind], [Adt], and [Intrinsic]
|
||||
|
||||
use super::{Adt, Def, DefKind, Intrinsic, TypeKind, ValueKind};
|
||||
use cl_ast::format::FmtPretty;
|
||||
use cl_ast::format::FmtAdapter;
|
||||
use std::{
|
||||
fmt::{self, Display, Write},
|
||||
iter,
|
||||
@ -31,13 +31,14 @@ where
|
||||
impl Display for Def<'_> {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
let Self { name, vis, meta, kind, source, module } = self;
|
||||
if !meta.is_empty() {
|
||||
writeln!(f, "#{meta:?}")?;
|
||||
}
|
||||
writeln!(f, "{vis}{name}: ")?;
|
||||
writeln!(f, "kind: {kind}")?;
|
||||
if !meta.is_empty() {
|
||||
writeln!(f, "meta: {meta:?}")?;
|
||||
}
|
||||
if let Some(source) = source {
|
||||
writeln!(f.pretty(), "source: {{\n{source}\n}}")?;
|
||||
writeln!(f, "source:")?;
|
||||
writeln!(f.indent(), "\n{source}")?;
|
||||
}
|
||||
write!(f, "module: {module}")
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user