mirror of
https://codeberg.org/unspeaker/tengri.git
synced 2025-12-06 11:46:42 +01:00
wip: finally, informative type errors from the macro
Some checks failed
/ build (push) Has been cancelled
Some checks failed
/ build (push) Has been cancelled
fixin mixin
This commit is contained in:
parent
abc87d3234
commit
583660c330
10 changed files with 152 additions and 205 deletions
|
|
@ -1,114 +1,70 @@
|
|||
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> (
|
||||
pub trait Receive<Type> {
|
||||
fn receive <'source> (&self, words: &mut TokenIter<'source>) -> Perhaps<Type>;
|
||||
fn receive_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)? {
|
||||
if let Some(value) = Receive::<Type>::receive(self, words)? {
|
||||
Ok(value)
|
||||
} else {
|
||||
Result::Err(format!("{}: {:?}", error().into(), words.peek().map(|x|x.value)).into())
|
||||
Result::Err(format!("receive: {}: {:?}", 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>)
|
||||
pub trait Provide<'n, State>: Sized + 'n {
|
||||
fn provide <'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> (
|
||||
fn provide_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)? {
|
||||
if let Some(value) = Provide::<State>::provide(state, words)? {
|
||||
Ok(value)
|
||||
} else {
|
||||
Result::Err(format!("{}: {:?}", error().into(), words.peek().map(|x|x.value)).into())
|
||||
Result::Err(format!("provide: {}: {:?}", 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
|
||||
/// Implement the [Receive] 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> {
|
||||
impl<'n, State, A: Provide<'n, State>> Provide<'n, State> for $T {
|
||||
fn provide <'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> {
|
||||
impl<'n, State, A: Provide<'n, State>, B: Provide<'n, State>> Provide<'n, State> for $T {
|
||||
fn provide <'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> {
|
||||
impl<'n> Provide<'n, $S> for $T {
|
||||
fn provide <'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())
|
||||
//}
|
||||
// auto impl graveyard:
|
||||
|
||||
//impl<'n, State: Receive<Type>, Type: 'n> Provide<'n, State> for Type {
|
||||
//fn provide <'source> (state: &State, words: &mut TokenIter<'source>)
|
||||
//-> Perhaps<Self>
|
||||
//{
|
||||
//state.take(words)
|
||||
//}
|
||||
//}
|
||||
|
||||
//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<'n, Type: Provide<'n, State>, State> Receive<Type> for State {
|
||||
//fn take <'source> (&self, words: &mut TokenIter<'source>) -> Perhaps<Type> {
|
||||
//Type::provide(self, words)
|
||||
//}
|
||||
//}
|
||||
|
||||
//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 {
|
||||
//}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue