forked from Orchid/orchid
base and extension fully compiles, host in good shape
This commit is contained in:
@@ -12,9 +12,9 @@ use crate::api;
|
||||
/// There are no ordering guarantees about these
|
||||
pub trait ExtPort {
|
||||
fn send<'a>(&'a self, msg: &'a [u8]) -> LocalBoxFuture<'a, ()>;
|
||||
fn recv<'a, 's: 'a>(
|
||||
&'s self,
|
||||
cb: Box<dyn FnOnce(&[u8]) -> LocalBoxFuture<'a, ()> + 'a>,
|
||||
fn recv<'a>(
|
||||
&'a self,
|
||||
cb: Box<dyn FnOnce(&[u8]) -> LocalBoxFuture<'_, ()> + 'a>,
|
||||
) -> LocalBoxFuture<'a, ()>;
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@ impl ExtInit {
|
||||
pub async fn send(&self, msg: &[u8]) { self.port.send(msg).await }
|
||||
pub async fn recv<'a, 's: 'a>(
|
||||
&'s self,
|
||||
cb: Box<dyn FnOnce(&[u8]) -> LocalBoxFuture<'a, ()> + 'a>,
|
||||
cb: Box<dyn FnOnce(&[u8]) -> LocalBoxFuture<'_, ()> + 'a>,
|
||||
) {
|
||||
self.port.recv(Box::new(cb)).await
|
||||
}
|
||||
|
||||
89
orchid-base/src/format.rs
Normal file
89
orchid-base/src/format.rs
Normal file
@@ -0,0 +1,89 @@
|
||||
use std::convert::Infallible;
|
||||
use std::iter;
|
||||
use std::rc::Rc;
|
||||
use std::str::FromStr;
|
||||
|
||||
use itertools::Itertools;
|
||||
use regex::Regex;
|
||||
|
||||
#[derive(Clone, Debug, Hash, PartialEq, Eq)]
|
||||
pub struct FmtUnit {
|
||||
pub subs: Vec<FmtUnit>,
|
||||
pub variants: Rc<Variants>,
|
||||
}
|
||||
impl FmtUnit {
|
||||
pub fn new(variants: Rc<Variants>, subs: impl IntoIterator<Item = FmtUnit>) -> Self {
|
||||
Self { subs: subs.into_iter().collect(), variants }
|
||||
}
|
||||
}
|
||||
impl<T> From<T> for FmtUnit
|
||||
where Variants: From<T>
|
||||
{
|
||||
fn from(value: T) -> Self { Self { subs: vec![], variants: Rc::new(Variants::from(value)) } }
|
||||
}
|
||||
impl FromStr for FmtUnit {
|
||||
type Err = Infallible;
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
Ok(Self { subs: vec![], variants: Rc::new(Variants::new([s])) })
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Hash, PartialEq, Eq)]
|
||||
pub enum FmtElement {
|
||||
Sub(u8),
|
||||
String(Rc<String>),
|
||||
InlineSub(u8),
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Hash, PartialEq, Eq)]
|
||||
pub struct Variants(pub Vec<Vec<FmtElement>>);
|
||||
impl Variants {
|
||||
pub fn new<'a>(variants: impl IntoIterator<Item = &'a str>) -> Self {
|
||||
let re = Regex::new(r"(?<tpl>\{\d+?-?\})|(\{\{)|(\}\})").unwrap();
|
||||
Self(Vec::from_iter(variants.into_iter().map(|s: &str| {
|
||||
let matches = re.captures_iter(s);
|
||||
let slots = matches.into_iter().filter_map(|m| m.name("tpl")).map(|tpl| {
|
||||
let no_opencurly = tpl.as_str().strip_prefix("{").expect("required by regex");
|
||||
let maybe_dash = no_opencurly.strip_suffix("}").expect("required by regex");
|
||||
let (num, had_dash) =
|
||||
maybe_dash.strip_suffix('-').map_or((maybe_dash, false), |s| (s, true));
|
||||
let idx = num.parse::<u8>().expect("Decimal digits required by regex");
|
||||
(tpl.range(), idx, had_dash)
|
||||
});
|
||||
(iter::once(None).chain(slots.into_iter().map(Some)).chain(None).tuple_windows())
|
||||
.flat_map(|(l, r)| {
|
||||
let string = match (l, &r) {
|
||||
(None, Some((r, ..))) => &s[..r.start],
|
||||
(Some((r1, ..)), Some((r2, ..))) => &s[r1.end..r2.start],
|
||||
(Some((r, ..)), None) => &s[r.end..],
|
||||
(None, None) => s,
|
||||
};
|
||||
let str_item = FmtElement::String(Rc::new(string.to_string()));
|
||||
match r {
|
||||
None => itertools::Either::Left([str_item]),
|
||||
Some((_, idx, inline)) => itertools::Either::Right([str_item, match inline {
|
||||
true => FmtElement::InlineSub(idx),
|
||||
false => FmtElement::Sub(idx),
|
||||
}]),
|
||||
}
|
||||
.into_iter()
|
||||
})
|
||||
.coalesce(|left, right| match (left, right) {
|
||||
(FmtElement::String(left), FmtElement::String(right)) =>
|
||||
Ok(FmtElement::String(Rc::new(left.to_string() + right.as_str()))),
|
||||
tuple => Err(tuple),
|
||||
})
|
||||
.collect_vec()
|
||||
})))
|
||||
}
|
||||
}
|
||||
impl From<String> for Variants {
|
||||
fn from(value: String) -> Self { Self(vec![vec![FmtElement::String(Rc::new(value))]]) }
|
||||
}
|
||||
impl From<Rc<String>> for Variants {
|
||||
fn from(value: Rc<String>) -> Self { Self(vec![vec![FmtElement::String(value)]]) }
|
||||
}
|
||||
impl FromStr for Variants {
|
||||
type Err = Infallible;
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> { Ok(Self::new([s])) }
|
||||
}
|
||||
@@ -247,7 +247,7 @@ impl Interner {
|
||||
tok
|
||||
}
|
||||
/// Extern an identifier; query the data it represents if not known locally
|
||||
async fn ex<M: InternMarker>(&self, marker: M) -> Tok<M::Interned> {
|
||||
pub async fn ex<M: InternMarker>(&self, marker: M) -> Tok<M::Interned> {
|
||||
if let Some(tok) = M::Interned::bimap(&mut *self.interners.lock().await).by_marker(marker) {
|
||||
return tok;
|
||||
}
|
||||
@@ -284,6 +284,7 @@ pub fn merge_retained(into: &mut api::Retained, from: &api::Retained) {
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use std::num::NonZero;
|
||||
use std::pin::Pin;
|
||||
|
||||
use orchid_api_traits::{Decode, enc_vec};
|
||||
use test_executors::spin_on;
|
||||
@@ -300,9 +301,11 @@ mod test {
|
||||
|
||||
#[test]
|
||||
fn test_coding() {
|
||||
let coded = api::TStr(NonZero::new(3u64).unwrap());
|
||||
let mut enc = &enc_vec(&coded)[..];
|
||||
api::TStr::decode(&mut enc);
|
||||
assert_eq!(enc, [], "Did not consume all of {enc:?}")
|
||||
spin_on(async {
|
||||
let coded = api::TStr(NonZero::new(3u64).unwrap());
|
||||
let mut enc = &enc_vec(&coded).await[..];
|
||||
api::TStr::decode(Pin::new(&mut enc)).await;
|
||||
assert_eq!(enc, [], "Did not consume all of {enc:?}")
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ pub mod clone;
|
||||
pub mod combine;
|
||||
pub mod error;
|
||||
pub mod event;
|
||||
pub mod format;
|
||||
pub mod id_store;
|
||||
pub mod interner;
|
||||
pub mod join;
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
use std::marker::PhantomData;
|
||||
use std::rc::Rc;
|
||||
use std::sync::Arc;
|
||||
|
||||
use async_std::stream;
|
||||
@@ -22,13 +23,14 @@ impl MacroSlot<'_> {
|
||||
|
||||
trait_set! {
|
||||
pub trait MacroAtomToApi<A> = for<'a> FnMut(&'a A) -> LocalBoxFuture<'a, api::MacroToken>;
|
||||
pub trait MacroAtomFromApi<'a, A> = FnMut(&api::Atom) -> MTok<'a, A>;
|
||||
pub trait MacroAtomFromApi<'a, A> =
|
||||
for<'b> FnMut(&'b api::Atom) -> LocalBoxFuture<'b, MTok<'a, A>>;
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct MTree<'a, A> {
|
||||
pub pos: Pos,
|
||||
pub tok: Arc<MTok<'a, A>>,
|
||||
pub tok: Rc<MTok<'a, A>>,
|
||||
}
|
||||
impl<'a, A> MTree<'a, A> {
|
||||
pub(crate) async fn from_api(
|
||||
@@ -38,7 +40,7 @@ impl<'a, A> MTree<'a, A> {
|
||||
) -> Self {
|
||||
Self {
|
||||
pos: Pos::from_api(&api.location, i).await,
|
||||
tok: Arc::new(MTok::from_api(&api.token, do_atom, i).await),
|
||||
tok: Rc::new(MTok::from_api(&api.token, i, do_atom).await),
|
||||
}
|
||||
}
|
||||
pub(crate) async fn to_api(&self, do_atom: &mut impl MacroAtomToApi<A>) -> api::MacroTree {
|
||||
@@ -66,17 +68,17 @@ pub enum MTok<'a, A> {
|
||||
impl<'a, A> MTok<'a, A> {
|
||||
pub(crate) async fn from_api(
|
||||
api: &api::MacroToken,
|
||||
do_atom: &mut impl MacroAtomFromApi<'a, A>,
|
||||
i: &Interner,
|
||||
do_atom: &mut impl MacroAtomFromApi<'a, A>,
|
||||
) -> Self {
|
||||
match_mapping!(&api, api::MacroToken => MTok::<'a, A> {
|
||||
Lambda(x => mtreev_from_api(x, do_atom, i).await, b => mtreev_from_api(b, do_atom, i).await),
|
||||
Lambda(x => mtreev_from_api(x, i, do_atom).await, b => mtreev_from_api(b, i, do_atom).await),
|
||||
Name(t => Sym::from_api(*t, i).await),
|
||||
Slot(tk => MacroSlot(*tk, PhantomData)),
|
||||
S(p.clone(), b => mtreev_from_api(b, do_atom, i).await),
|
||||
S(p.clone(), b => mtreev_from_api(b, i, do_atom).await),
|
||||
Ph(ph => Ph::from_api(ph, i).await),
|
||||
} {
|
||||
api::MacroToken::Atom(a) => do_atom(a)
|
||||
api::MacroToken::Atom(a) => do_atom(a).await
|
||||
})
|
||||
}
|
||||
pub(crate) async fn to_api(&self, do_atom: &mut impl MacroAtomToApi<A>) -> api::MacroToken {
|
||||
@@ -93,13 +95,13 @@ impl<'a, A> MTok<'a, A> {
|
||||
MTok::Atom(a) => do_atom(a).await,
|
||||
})
|
||||
}
|
||||
pub fn at(self, pos: Pos) -> MTree<'a, A> { MTree { pos, tok: Arc::new(self) } }
|
||||
pub fn at(self, pos: Pos) -> MTree<'a, A> { MTree { pos, tok: Rc::new(self) } }
|
||||
}
|
||||
|
||||
pub async fn mtreev_from_api<'a, 'b, A>(
|
||||
api: impl IntoIterator<Item = &'b api::MacroTree>,
|
||||
do_atom: &mut impl MacroAtomFromApi<'a, A>,
|
||||
i: &Interner,
|
||||
do_atom: &mut impl MacroAtomFromApi<'a, A>,
|
||||
) -> Vec<MTree<'a, A>> {
|
||||
let do_atom_lk = Mutex::new(do_atom);
|
||||
stream::from_iter(api)
|
||||
|
||||
@@ -6,7 +6,7 @@ use orchid_api_traits::{Decode, Encode};
|
||||
|
||||
pub async fn send_msg(mut write: Pin<&mut impl Write>, msg: &[u8]) -> io::Result<()> {
|
||||
let mut len_buf = vec![];
|
||||
u32::try_from(msg.len()).unwrap().encode(&mut len_buf);
|
||||
u32::try_from(msg.len()).unwrap().encode(Pin::new(&mut len_buf)).await;
|
||||
write.write_all(&len_buf).await?;
|
||||
write.write_all(msg).await?;
|
||||
write.flush().await
|
||||
@@ -15,7 +15,7 @@ pub async fn send_msg(mut write: Pin<&mut impl Write>, msg: &[u8]) -> io::Result
|
||||
pub async fn recv_msg(mut read: Pin<&mut impl Read>) -> io::Result<Vec<u8>> {
|
||||
let mut len_buf = [0u8; (u32::BITS / 8) as usize];
|
||||
read.read_exact(&mut len_buf).await?;
|
||||
let len = u32::decode(&mut &len_buf[..]);
|
||||
let len = u32::decode(Pin::new(&mut &len_buf[..])).await;
|
||||
let mut msg = vec![0u8; len as usize];
|
||||
read.read_exact(&mut msg).await?;
|
||||
Ok(msg)
|
||||
|
||||
@@ -33,6 +33,7 @@ impl<'a, 'b, A: AtomRepr, X: ExtraTok> Snippet<'a, 'b, A, X> {
|
||||
pub async fn i<T: Interned>(&self, arg: &(impl Internable<Interned = T> + ?Sized)) -> Tok<T> {
|
||||
self.interner.i(arg).await
|
||||
}
|
||||
pub fn interner(&self) -> &'a Interner { self.interner }
|
||||
pub fn split_at(self, pos: u32) -> (Self, Self) {
|
||||
let Self { prev, cur, interner } = self;
|
||||
let fst = Self { prev, cur: &cur[..pos as usize], interner };
|
||||
@@ -177,7 +178,7 @@ pub async fn expect_tok<'a, 'b, A: AtomRepr, X: ExtraTok>(
|
||||
Token::Name(n) if *n == tok => Ok(Parsed { output: (), tail }),
|
||||
t => Err(mk_errv(
|
||||
snip.i("Expected specific keyword").await,
|
||||
format!("Expected {tok} but found {t}"),
|
||||
format!("Expected {tok} but found {:?}", t.print().await),
|
||||
[Pos::Range(head.range.clone()).into()],
|
||||
)),
|
||||
}
|
||||
@@ -280,7 +281,7 @@ pub async fn parse_multiname<'a, 'b, A: AtomRepr, X: ExtraTok>(
|
||||
t => {
|
||||
return Err(mk_errv(
|
||||
tail.i("Unrecognized name end").await,
|
||||
format!("Names cannot end with {t} tokens"),
|
||||
format!("Names cannot end with {:?} tokens", t.print().await),
|
||||
[Pos::Range(name.range.clone()).into()],
|
||||
));
|
||||
},
|
||||
|
||||
@@ -4,6 +4,7 @@ use std::future::Future;
|
||||
use std::marker::PhantomData;
|
||||
use std::mem;
|
||||
use std::ops::{BitAnd, Deref};
|
||||
use std::pin::Pin;
|
||||
use std::sync::Arc;
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
|
||||
@@ -74,7 +75,7 @@ impl<'a, MS: MsgSet + 'static> RequestHandle<'a, MS> {
|
||||
pub async fn respond(&self, response: &impl Encode) -> Receipt<'a> {
|
||||
assert!(!self.fulfilled.swap(true, Ordering::Relaxed), "Already responded to {}", self.id);
|
||||
let mut buf = (!self.id).to_be_bytes().to_vec();
|
||||
response.encode(&mut buf);
|
||||
response.encode(Pin::new(&mut buf)).await;
|
||||
let mut send = clone_box(&*self.reqnot().0.lock().await.send);
|
||||
(send)(&buf, self.parent.clone()).await;
|
||||
Receipt(PhantomData)
|
||||
@@ -126,18 +127,19 @@ impl<T: MsgSet> ReqNot<T> {
|
||||
let mut g = self.0.lock().await;
|
||||
let (id, payload) = get_id(message);
|
||||
if id == 0 {
|
||||
let mut notif = clone_box(&*g.notif);
|
||||
let mut notif_cb = clone_box(&*g.notif);
|
||||
mem::drop(g);
|
||||
notif(<T::In as Channel>::Notif::decode(&mut &payload[..]), self.clone()).await
|
||||
let notif_val = <T::In as Channel>::Notif::decode(Pin::new(&mut &payload[..])).await;
|
||||
notif_cb(notif_val, self.clone()).await
|
||||
} else if 0 < id.bitand(1 << 63) {
|
||||
let sender = g.responses.remove(&!id).expect("Received response for invalid message");
|
||||
sender.send(message.to_vec()).await.unwrap();
|
||||
} else {
|
||||
let message = <T::In as Channel>::Req::decode(&mut &payload[..]);
|
||||
let mut req = clone_box(&*g.req);
|
||||
let message = <T::In as Channel>::Req::decode(Pin::new(&mut &payload[..])).await;
|
||||
let mut req_cb = clone_box(&*g.req);
|
||||
mem::drop(g);
|
||||
let rn = self.clone();
|
||||
req(RequestHandle::new(rn, id), message).await;
|
||||
req_cb(RequestHandle::new(rn, id), message).await;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -145,7 +147,7 @@ impl<T: MsgSet> ReqNot<T> {
|
||||
let mut send = clone_box(&*self.0.lock().await.send);
|
||||
let mut buf = vec![0; 8];
|
||||
let msg: <T::Out as Channel>::Notif = notif.into();
|
||||
msg.encode(&mut buf);
|
||||
msg.encode(Pin::new(&mut buf)).await;
|
||||
send(&buf, self.clone()).await
|
||||
}
|
||||
}
|
||||
@@ -180,7 +182,7 @@ impl<T: MsgSet> DynRequester for ReqNot<T> {
|
||||
let id = g.id;
|
||||
g.id += 1;
|
||||
let mut buf = id.to_be_bytes().to_vec();
|
||||
req.encode(&mut buf);
|
||||
req.encode(Pin::new(&mut buf)).await;
|
||||
let (send, recv) = channel::bounded(1);
|
||||
g.responses.insert(id, send);
|
||||
let mut send = clone_box(&*g.send);
|
||||
@@ -206,7 +208,7 @@ pub trait Requester: DynRequester {
|
||||
}
|
||||
impl<This: DynRequester + ?Sized> Requester for This {
|
||||
async fn request<R: Request + Into<Self::Transfer>>(&self, data: R) -> R::Response {
|
||||
R::Response::decode(&mut &self.raw_request(data.into()).await[..])
|
||||
R::Response::decode(Pin::new(&mut &self.raw_request(data.into()).await[..])).await
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use std::borrow::Borrow;
|
||||
use std::cell::RefCell;
|
||||
use std::fmt::{self, Debug, Display};
|
||||
use std::future::{Future, ready};
|
||||
use std::iter;
|
||||
use std::marker::PhantomData;
|
||||
use std::ops::Range;
|
||||
@@ -9,7 +9,7 @@ use std::sync::Arc;
|
||||
pub use api::PhKind;
|
||||
use async_std::stream;
|
||||
use async_std::sync::Mutex;
|
||||
use futures::future::LocalBoxFuture;
|
||||
use futures::future::{LocalBoxFuture, join_all};
|
||||
use futures::{FutureExt, StreamExt};
|
||||
use itertools::Itertools;
|
||||
use never::Never;
|
||||
@@ -47,15 +47,22 @@ pub fn recur<'a, A: AtomRepr, X: ExtraTok>(
|
||||
})
|
||||
}
|
||||
|
||||
pub trait AtomRepr: fmt::Display + Clone + fmt::Debug {
|
||||
pub trait AtomRepr: Clone {
|
||||
type Ctx: ?Sized;
|
||||
fn from_api(api: &api::Atom, pos: Pos, ctx: &mut Self::Ctx) -> Self;
|
||||
fn to_api(&self) -> orchid_api::Atom;
|
||||
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;
|
||||
fn from_api(_: &api::Atom, _: Pos, _: &mut Self::Ctx) -> Self { panic!() }
|
||||
fn to_api(&self) -> orchid_api::Atom { match *self {} }
|
||||
#[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 {}) }
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq)]
|
||||
@@ -79,7 +86,7 @@ impl<'b, A: AtomRepr, X: ExtraTok> TokTree<'b, A, X> {
|
||||
pub async fn from_api(tt: &api::TokenTree, ctx: &mut A::Ctx, i: &Interner) -> Self {
|
||||
let tok = match_mapping!(&tt.token, api::Token => Token::<'b, A, X> {
|
||||
BR, NS,
|
||||
Atom(a => A::from_api(a, Pos::Range(tt.range.clone()), ctx)),
|
||||
Atom(a => A::from_api(a, Pos::Range(tt.range.clone()), ctx).await),
|
||||
Bottom(e => OrcErrv::from_api(e, i).await),
|
||||
LambdaHead(arg => ttv_from_api(arg, ctx, i).await),
|
||||
Name(n => Tok::from_api(*n, i).await),
|
||||
@@ -94,7 +101,7 @@ impl<'b, A: AtomRepr, X: ExtraTok> TokTree<'b, A, X> {
|
||||
|
||||
pub async fn to_api(&self, do_extra: &mut impl RefDoExtra<X>) -> api::TokenTree {
|
||||
let token = match_mapping!(&self.tok, Token => api::Token {
|
||||
Atom(a.to_api()),
|
||||
Atom(a.to_api().await),
|
||||
BR,
|
||||
NS,
|
||||
Bottom(e.to_api()),
|
||||
@@ -111,20 +118,20 @@ impl<'b, A: AtomRepr, X: ExtraTok> TokTree<'b, A, X> {
|
||||
api::TokenTree { range: self.range.clone(), token }
|
||||
}
|
||||
|
||||
pub fn into_api(
|
||||
pub async fn into_api(
|
||||
self,
|
||||
do_extra: &mut impl FnMut(X, Range<u32>) -> api::TokenTree,
|
||||
) -> api::TokenTree {
|
||||
let token = match self.tok {
|
||||
Token::Atom(a) => api::Token::Atom(a.to_api()),
|
||||
Token::Atom(a) => api::Token::Atom(a.to_api().await),
|
||||
Token::BR => api::Token::BR,
|
||||
Token::NS => api::Token::NS,
|
||||
Token::Bottom(e) => api::Token::Bottom(e.to_api()),
|
||||
Token::Comment(c) => api::Token::Comment(c.clone()),
|
||||
Token::LambdaHead(arg) => api::Token::LambdaHead(ttv_into_api(arg, do_extra)),
|
||||
Token::LambdaHead(arg) => api::Token::LambdaHead(ttv_into_api(arg, do_extra).await),
|
||||
Token::Name(n) => api::Token::Name(n.to_api()),
|
||||
Token::Slot(tt) => api::Token::Slot(tt.ticket()),
|
||||
Token::S(p, b) => api::Token::S(p, ttv_into_api(b, do_extra)),
|
||||
Token::S(p, b) => api::Token::S(p, ttv_into_api(b, do_extra).await),
|
||||
Token::Ph(Ph { kind, name }) =>
|
||||
api::Token::Ph(api::Placeholder { name: name.to_api(), kind }),
|
||||
Token::X(x) => return do_extra(x, self.range.clone()),
|
||||
@@ -146,10 +153,7 @@ 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)
|
||||
}
|
||||
}
|
||||
|
||||
impl<A: AtomRepr, X: ExtraTok> Display for TokTree<'_, A, X> {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "{}", self.tok) }
|
||||
pub async fn print(&self) -> String { self.tok.print().await }
|
||||
}
|
||||
|
||||
pub async fn ttv_from_api<A: AtomRepr, X: ExtraTok>(
|
||||
@@ -161,7 +165,7 @@ pub async fn ttv_from_api<A: AtomRepr, X: ExtraTok>(
|
||||
stream::from_iter(tokv.into_iter())
|
||||
.then(|t| async {
|
||||
let t = t;
|
||||
TokTree::<A, X>::from_api(t.borrow(), *ctx_lk.lock().await, i).await
|
||||
TokTree::<A, X>::from_api(t.borrow(), *ctx_lk.lock().await, i).boxed_local().await
|
||||
})
|
||||
.collect()
|
||||
.await
|
||||
@@ -178,11 +182,15 @@ pub async fn ttv_to_api<'a, A: AtomRepr, X: ExtraTok>(
|
||||
output
|
||||
}
|
||||
|
||||
pub fn ttv_into_api<'a, A: AtomRepr, X: ExtraTok>(
|
||||
pub async fn ttv_into_api<'a, A: AtomRepr, X: ExtraTok>(
|
||||
tokv: impl IntoIterator<Item = TokTree<'a, A, X>>,
|
||||
do_extra: &mut impl FnMut(X, Range<u32>) -> api::TokenTree,
|
||||
) -> Vec<api::TokenTree> {
|
||||
tokv.into_iter().map(|t| t.into_api(do_extra)).collect_vec()
|
||||
let mut new_tokv = Vec::new();
|
||||
for item in tokv {
|
||||
new_tokv.push(item.into_api(do_extra).await)
|
||||
}
|
||||
new_tokv
|
||||
}
|
||||
|
||||
/// This takes a position and not a range because it assigns the range to
|
||||
@@ -237,50 +245,32 @@ impl<'a, A: AtomRepr, X: ExtraTok> Token<'a, A, X> {
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
impl<A: AtomRepr, X: ExtraTok> Display for Token<'_, A, X> {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
thread_local! {
|
||||
static PAREN_LEVEL: RefCell<usize> = 0.into();
|
||||
}
|
||||
fn get_indent() -> usize { PAREN_LEVEL.with_borrow(|t| *t) }
|
||||
fn with_indent<T>(f: impl FnOnce() -> T) -> T {
|
||||
PAREN_LEVEL.with_borrow_mut(|t| *t += 1);
|
||||
let r = f();
|
||||
PAREN_LEVEL.with_borrow_mut(|t| *t -= 1);
|
||||
r
|
||||
}
|
||||
pub async fn print(&self) -> String {
|
||||
match self {
|
||||
Self::Atom(a) => f.write_str(&indent(&format!("{a} "), get_indent(), false)),
|
||||
Self::BR => write!(f, "\n{}", " ".repeat(get_indent())),
|
||||
Self::Bottom(err) if err.len() == 1 => write!(f, "Bottom({}) ", err.one().unwrap()),
|
||||
Self::Bottom(err) => {
|
||||
write!(f, "Botttom(\n{}) ", indent(&err.to_string(), get_indent() + 1, true))
|
||||
},
|
||||
Self::Comment(c) => write!(f, "--[{c}]-- "),
|
||||
Self::LambdaHead(arg) => with_indent(|| write!(f, "\\ {} . ", ttv_fmt(arg))),
|
||||
Self::NS => f.write_str(":: "),
|
||||
Self::Name(n) => write!(f, "{n} "),
|
||||
Self::Slot(th) => write!(f, "{th} "),
|
||||
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 => write!(f, "${name}"),
|
||||
PhKind::Scalar => format!("${name}"),
|
||||
PhKind::Vector { at_least_one, priority } => {
|
||||
if *at_least_one {
|
||||
write!(f, ".")?
|
||||
}
|
||||
write!(f, "..${name}")?;
|
||||
if 0 < *priority { write!(f, "{priority}") } else { Ok(()) }
|
||||
let prefix = if *at_least_one { "..." } else { ".." };
|
||||
let suffix = if 0 < *priority { format!(":{priority}") } else { String::new() };
|
||||
format!("{prefix}${name}{suffix}")
|
||||
},
|
||||
},
|
||||
Self::S(p, b) => {
|
||||
let (lp, rp, _) = PARENS.iter().find(|(_, _, par)| par == p).unwrap();
|
||||
write!(f, "{lp} ")?;
|
||||
with_indent(|| f.write_str(&ttv_fmt(b)))?;
|
||||
write!(f, "{rp} ")
|
||||
format!("{lp} {}{rp} ", indent(&ttv_fmt(b).await))
|
||||
},
|
||||
Self::X(x) => write!(f, "{x} "),
|
||||
Self::Macro(None) => write!(f, "macro "),
|
||||
Self::Macro(Some(prio)) => write!(f, "macro({prio})"),
|
||||
Self::X(x) => format!("{x} "),
|
||||
Self::Macro(None) => "macro ".to_string(),
|
||||
Self::Macro(Some(prio)) => format!("macro({prio})"),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -290,21 +280,13 @@ pub fn ttv_range(ttv: &[TokTree<'_, impl AtomRepr, impl ExtraTok>]) -> Range<u32
|
||||
ttv.first().unwrap().range.start..ttv.last().unwrap().range.end
|
||||
}
|
||||
|
||||
pub fn ttv_fmt<'a: 'b, 'b>(
|
||||
pub async fn ttv_fmt<'a: 'b, 'b>(
|
||||
ttv: impl IntoIterator<Item = &'b TokTree<'a, impl AtomRepr + 'b, impl ExtraTok + 'b>>,
|
||||
) -> String {
|
||||
ttv.into_iter().join("")
|
||||
join_all(ttv.into_iter().map(|tt| tt.print())).await.join("")
|
||||
}
|
||||
|
||||
pub fn indent(s: &str, lvl: usize, first: bool) -> String {
|
||||
if first {
|
||||
s.replace("\n", &("\n".to_string() + &" ".repeat(lvl)))
|
||||
} else if let Some((fst, rest)) = s.split_once('\n') {
|
||||
fst.to_string() + "\n" + &indent(rest, lvl, true)
|
||||
} else {
|
||||
s.to_string()
|
||||
}
|
||||
}
|
||||
pub fn indent(s: &str) -> String { s.replace("\n", "\n ") }
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Ph {
|
||||
|
||||
Reference in New Issue
Block a user