wip: directionalize!

can't fit all into 1 trait because of directionality
of trait implementation rules and constraints :(
This commit is contained in:
🪞👃🪞 2025-05-20 18:48:55 +03:00
parent f797a7143d
commit 7c1cddc759
10 changed files with 221 additions and 222 deletions

View file

@ -1,49 +1,61 @@
use crate::*;
pub trait Dsl<State>: Sized {
fn take_from <'state, 'source: 'state> (state: &'state State, _: &mut TokenIter<'source>)
-> Perhaps<Self>
{
unimplemented!()
}
fn take_from_or_fail <'state, 'source: 'state> (
state: &'state State,
pub trait Dsl<Other>: Sized {
fn take <'state, 'source: 'state> (
&'state self,
token: &mut TokenIter<'source>
)
-> Perhaps<Other>;
fn take_or_fail <'state, 'source: 'state> (
&'state self,
token: &mut TokenIter<'source>,
error: impl Into<Box<dyn std::error::Error>>
) -> Usually<Self> {
if let Some(value) = Dsl::<State>::take_from(state, token)? {
) -> Usually<Other> {
if let Some(value) = Dsl::<Other>::take(self, token)? {
Ok(value)
} else {
Result::Err(error.into())
}
}
}
impl<T, U: Dsl<T>> DslFrom<U> for T {}
pub trait DslFrom<T: Dsl<Self>>: Sized {
pub trait FromDsl<State>: Sized {
fn take_from <'state, 'source: 'state> (state: &'state State, token: &mut TokenIter<'source>)
-> Perhaps<Self>;
fn take_from_or_fail <'state, 'source: 'state> (
state: &'state State,
token: &mut TokenIter<'source>,
error: impl Into<Box<dyn std::error::Error>>
) -> Usually<Self> {
if let Some(value) = FromDsl::<State>::take_from(state, token)? {
Ok(value)
} else {
Result::Err(error.into())
}
}
}
impl<T: FromDsl<State>, State> Dsl<T> for State {
fn take <'state, 'source: 'state> (&'state self, token: &mut TokenIter<'source>)
-> Perhaps<T>
{
T::take_from(self, token)
}
fn take_or_fail <'state, 'source: 'state> (
&'state self,
token: &mut TokenIter<'source>,
error: impl Into<Box<dyn std::error::Error>>
) -> Usually<T> {
T::take_from_or_fail(self, token, error)
FromDsl::take_from(self, token)
}
}
//impl<State: Dsl<T>, T> FromDsl<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! dsl {
($T:ty: |$self:ident:$S:ty, $iter:ident|$expr:expr) => {
impl ::tengri::dsl::Dsl<$S> for $T {
#[macro_export] macro_rules! from_dsl {
($T:ty: |$state:ident:$S:ty, $words:ident|$expr:expr) => {
impl ::tengri::dsl::FromDsl<$S> for $T {
fn take_from <'state, 'source: 'state> (
state: &'state $S,
$iter: &mut ::tengri::dsl::TokenIter<'source>,
$state: &'state $S,
$words: &mut ::tengri::dsl::TokenIter<'source>,
) -> ::tengri::Perhaps<$T> {
$expr
}