cl-ast: Move matched brace indenter out of ast_impl (it doesn't impl the ast)

This commit is contained in:
John 2024-03-01 02:44:35 -06:00
parent 276f0b1031
commit 1eec1b06ce
4 changed files with 108 additions and 101 deletions

View File

@ -563,106 +563,6 @@ mod display {
}
}
pub mod format {
//! Code formatting for the [AST](super::super)
use std::{
io::{Result, Write as IoWrite},
ops::{Deref, DerefMut},
};
/// Trait which adds a function to [Writers](IoWrite) to turn them into [Prettifier]
pub trait Pretty {
/// Indents code according to the number of matched curly braces
fn pretty(self) -> Prettifier<'static, Self>
where Self: IoWrite + Sized;
}
impl<W: IoWrite> Pretty for W {
fn pretty(self) -> Prettifier<'static, Self>
where Self: IoWrite + Sized {
Prettifier::new(self)
}
}
pub struct Prettifier<'i, T: IoWrite> {
level: isize,
indent: &'i str,
writer: T,
}
impl<'i, W: IoWrite> 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 }
}
pub fn indent<'scope>(&'scope mut self) -> Indent<'scope, 'i, W> {
Indent::new(self)
}
fn write_indentation(&mut self) -> Result<usize> {
let Self { level, indent, writer } = self;
let mut count = 0;
for _ in 0..*level {
count += writer.write(indent.as_bytes())?;
}
Ok(count)
}
}
impl<W: IoWrite> From<W> for Prettifier<'static, W> {
fn from(value: W) -> Self {
Self::new(value)
}
}
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.write_indentation()?;
}
}
}
Ok(size)
}
fn flush(&mut self) -> std::io::Result<()> {
self.writer.flush()
}
}
pub struct Indent<'scope, 'i, T: IoWrite> {
formatter: &'scope mut Prettifier<'i, T>,
}
impl<'s, 'i, T: IoWrite> Indent<'s, 'i, T> {
pub fn new(formatter: &'s mut Prettifier<'i, T>) -> Self {
formatter.level += 1;
Self { formatter }
}
}
impl<'s, 'i, T: IoWrite> Deref for Indent<'s, 'i, T> {
type Target = Prettifier<'i, T>;
fn deref(&self) -> &Self::Target {
self.formatter
}
}
impl<'s, 'i, T: IoWrite> DerefMut for Indent<'s, 'i, T> {
fn deref_mut(&mut self) -> &mut Self::Target {
self.formatter
}
}
impl<'s, 'i, T: IoWrite> Drop for Indent<'s, 'i, T> {
fn drop(&mut self) {
self.formatter.level -= 1;
}
}
}
mod convert {
//! Converts between major enums and enum variants

106
cl-ast/src/format.rs Normal file
View File

@ -0,0 +1,106 @@
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)
}
}
/// 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)
}
}
/// 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,
}
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,
_ => (),
}
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(())
}
}
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()
}
}

View File

@ -15,6 +15,7 @@
use cl_structures::span::*;
pub mod ast_impl;
pub mod format;
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
pub enum Mutability {

View File

@ -84,7 +84,7 @@ pub mod program {
env::Environment, error::IResult, interpret::Interpret, temp_type_impl::ConValue,
};
use cl_ast::{self as ast, ast_impl::format::Pretty};
use cl_ast::{self as ast, format::*};
use cl_lexer::Lexer;
use cl_parser::{error::PResult, Parser};
// use conlang::resolver::{error::TyResult, Resolver};