From f315fb5af7eae328a64d25ca6aeffc1de87e0521 Mon Sep 17 00:00:00 2001 From: John Date: Thu, 18 Apr 2024 20:47:28 -0500 Subject: [PATCH] cl-ast: Overhaul pretty-printing using std::fmt::Write adapters. Now you don't have to import cl_ast::format::*!!! --- cl-ast/src/ast_impl.rs | 256 ++++++++++++++++------------ cl-ast/src/format.rs | 154 +++++++---------- cl-interpret/src/lib.rs | 4 +- cl-repl/examples/typeck.rs | 8 +- cl-repl/src/lib.rs | 14 +- cl-typeck/src/definition/display.rs | 11 +- 6 files changed, 228 insertions(+), 219 deletions(-) diff --git a/cl-ast/src/ast_impl.rs b/cl-ast/src/ast_impl.rs index 832aaa4..10562db 100644 --- a/cl-ast/src/ast_impl.rs +++ b/cl-ast/src/ast_impl.rs @@ -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( + iterable: impl IntoIterator, + 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| { - for (idx, (arg, ty)) in bind.iter().zip(types.iter()).enumerate() { - if idx != 0 { - f.write_str(", ")?; - } - write!(f, "{arg}: {ty}")?; + { + let mut f = f.delimit(INLINE_PARENS); + for (idx, (arg, ty)) in bind.iter().zip(types.iter()).enumerate() { + if idx != 0 { + f.write_str(", ")?; } - Ok(()) - }, - INLINE_PARENS, - )(f)?; + write!(f, "{arg}: {ty}")?; + } + } 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 { diff --git a/cl-ast/src/format.rs b/cl-ast/src/format.rs index 070fa4b..fb934da 100644 --- a/cl-ast/src/format.rs +++ b/cl-ast/src/format.rs @@ -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 FmtAdapter for W {} +pub trait FmtAdapter: Write { + fn indent(&mut self) -> Indent { + 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 FmtPretty for W {} -impl IoPretty for W { - fn pretty(self) -> Prettifier<'static, Self> { - Prettifier::new(self) + fn delimit(&mut self, delim: Delimiters) -> Delimit { + 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 { - 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()?; - } +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.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 { - 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: "]" }; +} diff --git a/cl-interpret/src/lib.rs b/cl-interpret/src/lib.rs index a8f0f85..f9fbdcf 100644 --- a/cl-interpret/src/lib.rs +++ b/cl-interpret/src/lib.rs @@ -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()) diff --git a/cl-repl/examples/typeck.rs b/cl-repl/examples/typeck.rs index e8694c1..099a5d1 100644 --- a/cl-repl/examples/typeck.rs +++ b/cl-repl/examples/typeck.rs @@ -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> { fn pretty_def(def: &Def, id: impl 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 { 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> { diff --git a/cl-repl/src/lib.rs b/cl-repl/src/lib.rs index fe8137c..cd05e63 100644 --- a/cl-repl/src/lib.rs +++ b/cl-repl/src/lib.rs @@ -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 { diff --git a/cl-typeck/src/definition/display.rs b/cl-typeck/src/definition/display.rs index 6b7f399..8f60e24 100644 --- a/cl-typeck/src/definition/display.rs +++ b/cl-typeck/src/definition/display.rs @@ -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}") }