dsl: use only Dsl trait

This commit is contained in:
🪞👃🪞 2025-05-19 00:06:03 +03:00
parent 3bc739328e
commit 90f5699fff
11 changed files with 430 additions and 406 deletions

View file

@ -1,55 +1,75 @@
use crate::*;
/// Map EDN tokens to parameters of a given type for a given context
/// TODO: Replace both [Context] and [TryFromDsl] with this trait
/// which returns a [Result].
/// Implement the [Dsl] trait, which boils down to
/// specifying two types and providing an expression.
#[macro_export] macro_rules! dsl {
($T:ty: |$self:ident:$S:ty, $iter:ident|$expr:expr) => {
impl ::tengri::dsl::Dsl<$T> for $S {
fn take <'state, 'source> (
&'state $self, $iter: &mut ::tengri::dsl::TokenIter<'source>,
) -> ::tengri::Perhaps<$T> {
$expr
}
}
}
}
/// Maps a sequencer of EDN tokens to parameters of supported types
/// for a given context.
pub trait Dsl<U>: Sized {
fn take <'state, 'source> (_: &'state Self, _: &mut TokenIter<'source>) -> Perhaps<U> {
Ok(None)
fn take <'state, 'source> (
&'state self,
_: &mut TokenIter<'source>
) -> Perhaps<U> {
unimplemented!()
}
fn take_or_fail <'state, 'source> (
state: &'state Self, iter: &mut TokenIter<'source>
&'state self,
token: &mut TokenIter<'source>,
error: impl Into<Box<dyn std::error::Error>>
) -> Usually<U> {
if let Some(value) = Self::take(state, iter)? {
if let Some(value) = Dsl::<U>::take(self, token)? {
Ok(value)
} else {
Result::Err("not found".into()) // TODO add info and error type
Result::Err(error.into())
}
}
}
/// Map EDN tokens to parameters of a given type for a given context
pub trait Context<'state, U>: Sized {
fn get <'source> (&'state self, _iter: &mut TokenIter<'source>) -> Option<U> {
None
}
//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: FromDsl<'state, X> {
}
impl<'state, T: Context<'state, U>, U> Context<'state, U> for &T {
fn get <'source> (&'state self, iter: &mut TokenIter<'source>) -> Option<U> {
(*self).get(iter)
}
}
//impl<T, U: FromDsl<T>> Dsl<U> for T {
//}
impl<'state, T: Context<'state, U>, U> Context<'state, U> for Option<T> {
fn get <'source> (&'state self, iter: &mut TokenIter<'source>) -> Option<U> {
self.as_ref().map(|s|s.get(iter)).flatten()
pub trait FromDsl<'state, T>: Sized {
fn take_from <'source: 'state> (
state: &'state T,
_token: &mut TokenIter<'source>
) -> Perhaps<Self> {
unimplemented!()
}
}
pub trait TryFromDsl<'state, T>: Sized {
fn try_from_expr <'source: 'state> (
_state: &'state T, _iter: &mut TokenIter<'source>
) -> Option<Self> {
None
}
fn try_from_atom <'source: 'state> (
state: &'state T, value: Value<'source>
) -> Option<Self> {
if let Exp(0, mut iter) = value {
return Self::try_from_expr(state, &mut iter)
fn take_from_or_fail <'source: 'state> (
state: &'state T,
token: &mut TokenIter<'source>,
error: impl Into<Box<dyn std::error::Error>>
) -> Usually<Self> {
if let Some(value) = FromDsl::<T>::take_from(state, token)? {
Ok(value)
} else {
Result::Err(error.into())
}
None
}
}