Formatter introduced

This commit is contained in:
2025-02-07 00:47:34 +01:00
parent b94d8a64cb
commit 40c5eaf3d5
23 changed files with 608 additions and 218 deletions

View File

@@ -1,9 +1,10 @@
use std::borrow::Borrow;
use std::fmt::{self, Debug, Display};
use std::future::{Future, ready};
use std::future::Future;
use std::iter;
use std::marker::PhantomData;
use std::ops::Range;
use std::rc::Rc;
use std::sync::Arc;
pub use api::PhKind;
@@ -16,16 +17,16 @@ use ordered_float::NotNan;
use trait_set::trait_set;
use crate::error::OrcErrv;
use crate::format::{FmtCtx, FmtUnit, Format, Variants};
use crate::interner::{Interner, Tok};
use crate::location::Pos;
use crate::name::PathSlice;
use crate::parse::Snippet;
use crate::tokens::PARENS;
use crate::{api, match_mapping};
use crate::{api, match_mapping, tl_cache};
trait_set! {
pub trait RecurCB<'a, A: AtomRepr, X: ExtraTok> = Fn(TokTree<'a, A, X>) -> TokTree<'a, A, X>;
pub trait ExtraTok = Display + Clone + fmt::Debug;
pub trait ExtraTok = Format + Clone + fmt::Debug;
pub trait RefDoExtra<X> =
for<'b> FnMut(&'b X, Range<u32>) -> LocalBoxFuture<'b, api::TokenTree>;
}
@@ -46,22 +47,15 @@ pub fn recur<'a, A: AtomRepr, X: ExtraTok>(
})
}
pub trait AtomRepr: Clone {
pub trait AtomRepr: Clone + Format {
type Ctx: ?Sized;
fn from_api(api: &api::Atom, pos: Pos, ctx: &mut Self::Ctx) -> impl Future<Output = Self>;
fn to_api(&self) -> impl Future<Output = orchid_api::Atom> + '_;
fn print(&self) -> impl Future<Output = String> + '_;
}
impl AtomRepr for Never {
type Ctx = Never;
#[allow(unreachable_code)]
fn from_api(_: &api::Atom, _: Pos, ctx: &mut Self::Ctx) -> impl Future<Output = Self> {
ready(match *ctx {})
}
#[allow(unreachable_code)]
fn to_api(&self) -> impl Future<Output = orchid_api::Atom> + '_ { ready(match *self {}) }
#[allow(unreachable_code)]
fn print(&self) -> impl Future<Output = String> + '_ { ready(match *self {}) }
async fn from_api(_: &api::Atom, _: Pos, ctx: &mut Self::Ctx) -> Self { match *ctx {} }
async fn to_api(&self) -> orchid_api::Atom { match *self {} }
}
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq)]
@@ -152,7 +146,11 @@ impl<'b, A: AtomRepr, X: ExtraTok> TokTree<'b, A, X> {
body.insert(0, Token::LambdaHead(arg).at(arg_range));
Token::S(Paren::Round, body).at(s_range)
}
pub async fn print(&self) -> String { self.tok.print().await }
}
impl<A: AtomRepr, X: ExtraTok> Format for TokTree<'_, A, X> {
async fn print<'a>(&'a self, c: &'a (impl FmtCtx + ?Sized + 'a)) -> FmtUnit {
self.tok.print(c).await
}
}
pub async fn ttv_from_api<A: AtomRepr, X: ExtraTok>(
@@ -245,32 +243,34 @@ impl<'a, A: AtomRepr, X: ExtraTok> Token<'a, A, X> {
_ => None,
}
}
pub async fn print(&self) -> String {
}
impl<A: AtomRepr, X: ExtraTok> Format for Token<'_, A, X> {
async fn print<'a>(&'a self, c: &'a (impl FmtCtx + ?Sized + 'a)) -> FmtUnit {
match self {
Self::Atom(a) => a.print().await,
Self::BR => "\n".to_string(),
Self::Bottom(err) if err.len() == 1 => format!("Bottom({}) ", err.one().unwrap()),
Self::Bottom(err) => format!("Botttom(\n{}) ", indent(&err.to_string())),
Self::Comment(c) => format!("--[{c}]-- "),
Self::LambdaHead(arg) => format!("\\ {} . ", indent(&ttv_fmt(arg).await)),
Self::NS => ":: ".to_string(),
Self::Name(n) => format!("{n} "),
Self::Slot(th) => format!("{th} "),
Self::Ph(Ph { kind, name }) => match &kind {
PhKind::Scalar => format!("${name}"),
PhKind::Vector { at_least_one, priority } => {
let prefix = if *at_least_one { "..." } else { ".." };
let suffix = if 0 < *priority { format!(":{priority}") } else { String::new() };
format!("{prefix}${name}{suffix}")
Self::Atom(a) => a.print(c).await,
Self::BR => "\n".to_string().into(),
Self::Bottom(err) if err.len() == 1 => format!("Bottom({}) ", err.one().unwrap()).into(),
Self::Bottom(err) => format!("Botttom(\n{}) ", indent(&err.to_string())).into(),
Self::Comment(c) => format!("--[{c}]--").into(),
Self::LambdaHead(arg) =>
FmtUnit::new(tl_cache!(Rc<Variants>: Rc::new(Variants::default().bounded("\\{0b}."))), [
ttv_fmt(arg, c).await,
]),
Self::NS => "::".to_string().into(),
Self::Name(n) => format!("{n}").into(),
Self::Slot(th) => format!("{th}").into(),
Self::Ph(ph) => format!("{ph}").into(),
Self::S(p, b) => FmtUnit::new(
match *p {
Paren::Round => Rc::new(Variants::default().bounded("({0b})")),
Paren::Curly => Rc::new(Variants::default().bounded("{{{0b}}}")),
Paren::Square => Rc::new(Variants::default().bounded("[{0b}]")),
},
},
Self::S(p, b) => {
let (lp, rp, _) = PARENS.iter().find(|(_, _, par)| par == p).unwrap();
format!("{lp} {}{rp} ", indent(&ttv_fmt(b).await))
},
Self::X(x) => format!("{x} "),
Self::Macro(None) => "macro ".to_string(),
Self::Macro(Some(prio)) => format!("macro({prio})"),
[ttv_fmt(b, c).await],
),
Self::X(x) => x.print(c).await,
Self::Macro(None) => "macro".to_string().into(),
Self::Macro(Some(prio)) => format!("macro({prio})").into(),
}
}
}
@@ -282,8 +282,9 @@ pub fn ttv_range(ttv: &[TokTree<'_, impl AtomRepr, impl ExtraTok>]) -> Range<u32
pub async fn ttv_fmt<'a: 'b, 'b>(
ttv: impl IntoIterator<Item = &'b TokTree<'a, impl AtomRepr + 'b, impl ExtraTok + 'b>>,
) -> String {
join_all(ttv.into_iter().map(|tt| tt.print())).await.join("")
c: &(impl FmtCtx + ?Sized),
) -> FmtUnit {
FmtUnit::sequence(" ", None, join_all(ttv.into_iter().map(|t| t.print(c))).await)
}
pub fn indent(s: &str) -> String { s.replace("\n", "\n ") }
@@ -301,6 +302,18 @@ impl Ph {
api::Placeholder { name: self.name.to_api(), kind: self.kind }
}
}
impl Display for Ph {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let n = &self.name;
match self.kind {
PhKind::Scalar => write!(f, "${n}"),
PhKind::Vector { priority: 0, at_least_one: true } => write!(f, "...${}", self.name),
PhKind::Vector { priority: p, at_least_one: true } => write!(f, "...${}:{}", self.name, p),
PhKind::Vector { priority: 0, at_least_one: false } => write!(f, "..${}", self.name),
PhKind::Vector { priority: p, at_least_one: false } => write!(f, "..${}:{}", self.name, p),
}
}
}
#[cfg(test)]
mod test {