tengri/dsl/src/dsl_provide.rs
unspeaker abc87d3234
Some checks are pending
/ build (push) Waiting to run
dsl, output: error handlers
2025-05-21 14:17:27 +03:00

114 lines
3.6 KiB
Rust

use crate::*;
pub trait Dsl<Type> {
fn take <'source> (&self, words: &mut TokenIter<'source>) -> Perhaps<Type>;
fn take_or_fail <'source, E: Into<Box<dyn std::error::Error>>, F: Fn()->E> (
&self, words: &mut TokenIter<'source>, error: F
) -> Usually<Type> {
if let Some(value) = Dsl::<Type>::take(self, words)? {
Ok(value)
} else {
Result::Err(format!("{}: {:?}", error().into(), words.peek().map(|x|x.value)).into())
}
}
}
impl<Type: Namespace<State>, State> Dsl<Type> for State {
fn take <'source> (&self, words: &mut TokenIter<'source>) -> Perhaps<Type> {
Namespace::take_from(self, words)
}
}
pub trait Namespace<State>: Sized {
fn take_from <'source> (state: &State, words: &mut TokenIter<'source>)
-> Perhaps<Self>;
fn take_from_or_fail <'source, E: Into<Box<dyn std::error::Error>>, F: Fn()->E> (
state: &State, words: &mut TokenIter<'source>, error: F
) -> Usually<Self> {
if let Some(value) = Namespace::<State>::take_from(state, words)? {
Ok(value)
} else {
Result::Err(format!("{}: {:?}", error().into(), words.peek().map(|x|x.value)).into())
}
}
}
//impl<State: Dsl<T>, T> Namespace<State> for T {
//fn take_from <'state, 'source: 'state> (state: &'state State, token: &mut TokenIter<'source>)
//-> Perhaps<Self>
//{
//Dsl::take(state, token)
//}
//}
/// Implement the [Dsl] trait, which boils down to
/// specifying two types and providing an expression.
#[macro_export] macro_rules! from_dsl {
(@a: $T:ty: |$state:ident, $words:ident|$expr:expr) => {
impl<State: Dsl<A>, A> Namespace<State> for $T {
fn take_from <'source> (
$state: &State,
$words: &mut TokenIter<'source>,
) -> Perhaps<$T> {
$expr
}
}
};
(@ab: $T:ty: |$state:ident, $words:ident|$expr:expr) => {
impl<State: Dsl<A> + Dsl<B>, A, B> Namespace<State> for $T {
fn take_from <'source> (
$state: &State,
$words: &mut TokenIter<'source>,
) -> Perhaps<$T> {
$expr
}
}
};
($T:ty: |$state:ident:$S:ty, $words:ident|$expr:expr) => {
impl Namespace<$S> for $T {
fn take_from <'source> (
$state: &$S,
$words: &mut TokenIter<'source>,
) -> Perhaps<$T> {
$expr
}
}
};
}
///// Maps a sequencer of EDN tokens to parameters of supported types
///// for a given context.
//pub trait Dsl<Value>: Sized {
//fn take <'state, 'source> (&'state self, _: &mut TokenIter<'source>) -> Perhaps<Value> {
//unimplemented!()
//}
//fn take_or_fail <'state, 'source> (
//&'state self,
//token: &mut TokenIter<'source>,
//error: impl Into<Box<dyn std::error::Error>>
//) -> Usually<Value> {
//if let Some(value) = Dsl::<Value>::take(self, token)? {
//Ok(value)
//} else {
//Result::Err(error.into())
//}
//}
//}
//impl<T: Dsl<U>, U> Dsl<U> for &T {
//fn take <'state, 'source> (&'state self, iter: &mut TokenIter<'source>) -> Perhaps<U> {
//(*self).take(iter)
//}
//}
//impl<T: Dsl<U>, U> Dsl<U> for Option<T> {
//fn take <'state, 'source> (&'state self, iter: &mut TokenIter<'source>) -> Perhaps<U> {
//Ok(self.as_ref().map(|s|s.take(iter)).transpose()?.flatten())
//}
//}
//impl<'state, X, Y> Dsl<X> for Y where Y: Dsl<'state, X> {
//}
//impl<T, U: Dsl<T>> Dsl<U> for T {
//}