mirror of
https://codeberg.org/unspeaker/tengri.git
synced 2025-12-06 11:46:42 +01:00
core, input: add flex_trait
This commit is contained in:
parent
360b404b69
commit
8cbd7dd8e8
7 changed files with 201 additions and 98 deletions
74
core/src/core_macros.rs
Normal file
74
core/src/core_macros.rs
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
use crate::*;
|
||||
|
||||
/// Define and reexport submodules.
|
||||
#[macro_export] macro_rules! modules(
|
||||
($($($feat:literal?)? $name:ident),* $(,)?) => { $(
|
||||
$(#[cfg(feature=$feat)])? mod $name;
|
||||
$(#[cfg(feature=$feat)])? pub use self::$name::*;
|
||||
)* };
|
||||
($($($feat:literal?)? $name:ident $body:block),* $(,)?) => { $(
|
||||
$(#[cfg(feature=$feat)])? mod $name $body
|
||||
$(#[cfg(feature=$feat)])? pub use self::$name::*;
|
||||
)* };
|
||||
);
|
||||
|
||||
/// Define a trait for various wrapper types. */
|
||||
#[macro_export] macro_rules! flex_trait_mut (
|
||||
($Trait:ident $(<$($A:ident:$T:ident),+>)? {
|
||||
$(fn $fn:ident (&mut $self:ident $(, $arg:ident:$ty:ty)*) -> $ret:ty $body:block)*
|
||||
})=>{
|
||||
pub trait $Trait $(<$($A: $T),+>)? {
|
||||
$(fn $fn (&mut $self $(,$arg:$ty)*) -> $ret $body)*
|
||||
}
|
||||
impl<$($($A: $T,)+)? _T_: $Trait $(<$($A),+>)?> $Trait $(<$($A),+>)? for &mut _T_ {
|
||||
$(fn $fn (&mut $self $(,$arg:$ty)*) -> $ret { (*$self).$fn($($arg),*) })*
|
||||
}
|
||||
impl<$($($A: $T,)+)? _T_: $Trait $(<$($A),+>)?> $Trait $(<$($A),+>)? for Option<_T_> {
|
||||
$(fn $fn (&mut $self $(,$arg:$ty)*) -> $ret {
|
||||
if let Some(this) = $self { this.$fn($($arg),*) } else { Ok(None) }
|
||||
})*
|
||||
}
|
||||
impl<$($($A: $T,)+)? _T_: $Trait $(<$($A),+>)?> $Trait $(<$($A),+>)? for ::std::sync::Mutex<_T_> {
|
||||
$(fn $fn (&mut $self $(,$arg:$ty)*) -> $ret { $self.get_mut().unwrap().$fn($($arg),*) })*
|
||||
}
|
||||
impl<$($($A: $T,)+)? _T_: $Trait $(<$($A),+>)?> $Trait $(<$($A),+>)? for ::std::sync::Arc<::std::sync::Mutex<_T_>> {
|
||||
$(fn $fn (&mut $self $(,$arg:$ty)*) -> $ret { $self.lock().unwrap().$fn($($arg),*) })*
|
||||
}
|
||||
impl<$($($A: $T,)+)? _T_: $Trait $(<$($A),+>)?> $Trait $(<$($A),+>)? for ::std::sync::RwLock<_T_> {
|
||||
$(fn $fn (&mut $self $(,$arg:$ty)*) -> $ret { $self.write().unwrap().$fn($($arg),*) })*
|
||||
}
|
||||
impl<$($($A: $T,)+)? _T_: $Trait $(<$($A),+>)?> $Trait $(<$($A),+>)? for ::std::sync::Arc<::std::sync::RwLock<_T_>> {
|
||||
$(fn $fn (&mut $self $(,$arg:$ty)*) -> $ret { $self.write().unwrap().$fn($($arg),*) })*
|
||||
}
|
||||
};
|
||||
);
|
||||
|
||||
/// Implement [`Debug`] in bulk.
|
||||
#[macro_export] macro_rules! impl_debug(($($S:ty|$self:ident,$w:ident|$body:block)*)=>{
|
||||
$(impl std::fmt::Debug for $S {
|
||||
fn fmt (&$self, $w: &mut std::fmt::Formatter) -> std::fmt::Result $body
|
||||
})* });
|
||||
|
||||
/// Implement [`From`] in bulk.
|
||||
#[macro_export] macro_rules! from(
|
||||
($(<$($lt:lifetime),+>)?|$state:ident:$Source:ty|$Target:ty=$cb:expr) => {
|
||||
impl $(<$($lt),+>)? From<$Source> for $Target {
|
||||
fn from ($state:$Source) -> Self { $cb }}};
|
||||
($($Struct:ty { $(
|
||||
$(<$($l:lifetime),* $($T:ident$(:$U:ident)?),*>)? ($source:ident: $From:ty) $expr:expr
|
||||
);+ $(;)? })*) => { $(
|
||||
$(impl $(<$($l),* $($T$(:$U)?),*>)? From<$From> for $Struct {
|
||||
fn from ($source: $From) -> Self { $expr } })+ )* }; );
|
||||
|
||||
/// Implement [Has].
|
||||
#[macro_export] macro_rules! has(($T:ty: |$self:ident : $S:ty| $x:expr) => {
|
||||
impl Has<$T> for $S {
|
||||
fn get (&$self) -> &$T { &$x }
|
||||
fn get_mut (&mut $self) -> &mut $T { &mut $x } } };);
|
||||
|
||||
/// Implement [MaybeHas].
|
||||
#[macro_export] macro_rules! maybe_has(
|
||||
($T:ty: |$self:ident : $S:ty| $x:block; $y:block $(;)?) => {
|
||||
impl MaybeHas<$T> for $S {
|
||||
fn get (&$self) -> Option<&$T> $x
|
||||
fn get_mut (&mut $self) -> Option<&mut $T> $y } };);
|
||||
|
|
@ -1,38 +1,13 @@
|
|||
mod core_macros;
|
||||
pub(crate) use std::error::Error;
|
||||
/// Standard result type.
|
||||
pub type Usually<T> = Result<T, Box<dyn Error>>;
|
||||
/// Standard optional result type.
|
||||
pub type Perhaps<T> = Result<Option<T>, Box<dyn Error>>;
|
||||
/// Implement [`Debug`] in bulk.
|
||||
#[macro_export] macro_rules! impl_debug(($($S:ty|$self:ident,$w:ident|$body:block)*)=>{
|
||||
$(impl std::fmt::Debug for $S {
|
||||
fn fmt (&$self, $w: &mut std::fmt::Formatter) -> std::fmt::Result $body
|
||||
})* });
|
||||
/// Implement [`From`] in bulk.
|
||||
#[macro_export] macro_rules! from(
|
||||
($(<$($lt:lifetime),+>)?|$state:ident:$Source:ty|$Target:ty=$cb:expr) => {
|
||||
impl $(<$($lt),+>)? From<$Source> for $Target {
|
||||
fn from ($state:$Source) -> Self { $cb }}};
|
||||
($($Struct:ty { $(
|
||||
$(<$($l:lifetime),* $($T:ident$(:$U:ident)?),*>)? ($source:ident: $From:ty) $expr:expr
|
||||
);+ $(;)? })*) => { $(
|
||||
$(impl $(<$($l),* $($T$(:$U)?),*>)? From<$From> for $Struct {
|
||||
fn from ($source: $From) -> Self { $expr } })+ )* }; );
|
||||
/// Type-dispatched `get` and `get_mut`.
|
||||
pub trait Has<T>: Send + Sync { fn get (&self) -> &T; fn get_mut (&mut self) -> &mut T; }
|
||||
/// Implement [Has].
|
||||
#[macro_export] macro_rules! has(($T:ty: |$self:ident : $S:ty| $x:expr) => {
|
||||
impl Has<$T> for $S {
|
||||
fn get (&$self) -> &$T { &$x }
|
||||
fn get_mut (&mut $self) -> &mut $T { &mut $x } } };);
|
||||
/// Type-dispatched `get` and `get_mut` that return an [Option]-wrapped result.
|
||||
pub trait MaybeHas<T>: Send + Sync { fn get (&self) -> Option<&T>; fn get_mut (&mut self) -> Option<&mut T>; }
|
||||
/// Implement [MaybeHas].
|
||||
#[macro_export] macro_rules! maybe_has(
|
||||
($T:ty: |$self:ident : $S:ty| $x:block; $y:block $(;)?) => {
|
||||
impl MaybeHas<$T> for $S {
|
||||
fn get (&$self) -> Option<&$T> $x
|
||||
fn get_mut (&mut $self) -> Option<&mut $T> $y } };);
|
||||
/// May compute a `RetVal` from `Args`.
|
||||
pub trait Eval<Args, RetVal> {
|
||||
/// A custom operation on [Args] that may return [Result::Err] or [Option::None].
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
//#![feature(adt_const_params)]
|
||||
//#![feature(type_alias_impl_trait)]
|
||||
#![feature(if_let_guard)]
|
||||
#![feature(impl_trait_in_fn_trait_return)]
|
||||
#![feature(const_precise_live_drops)]
|
||||
extern crate const_panic;
|
||||
|
|
@ -31,10 +32,6 @@ impl Dsl for std::sync::Arc<str> {
|
|||
fn src (&self) -> &str { self.as_ref() }
|
||||
}
|
||||
|
||||
impl<D: Dsl> Dsl for Option<D> {
|
||||
fn src (&self) -> &str { if let Some(dsl) = self { dsl.src() } else { "" } }
|
||||
}
|
||||
|
||||
impl<D: Dsl> Dsl for &D {
|
||||
fn src (&self) -> &str { (*self).src() }
|
||||
}
|
||||
|
|
@ -43,6 +40,14 @@ impl<D: Dsl> Dsl for &mut D {
|
|||
fn src (&self) -> &str { (**self).src() }
|
||||
}
|
||||
|
||||
impl<D: Dsl> Dsl for std::sync::Arc<D> {
|
||||
fn src (&self) -> &str { (*self).src() }
|
||||
}
|
||||
|
||||
impl<D: Dsl> Dsl for Option<D> {
|
||||
fn src (&self) -> &str { if let Some(dsl) = self { dsl.src() } else { "" } }
|
||||
}
|
||||
|
||||
/// DSL-specific result type.
|
||||
pub type DslResult<T> = Result<T, DslError>;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,9 +1,7 @@
|
|||
use crate::*;
|
||||
|
||||
macro_rules! iter_chars(($source:expr => |$i:ident, $c:ident|$val:expr)=>{
|
||||
while let Some((($i, $c), next)) = char_indices($source).next() {
|
||||
$source = next.as_str(); $val } });
|
||||
|
||||
macro_rules! def_peek_seek(($peek:ident, $seek:ident, $seek_start:ident, $seek_length:ident)=>{
|
||||
/// Find a slice corrensponding to a syntax token.
|
||||
const fn $peek (source: &str) -> DslPerhaps<&str> {
|
||||
|
|
@ -22,27 +20,56 @@ macro_rules! def_peek_seek(($peek:ident, $seek:ident, $seek_start:ident, $seek_l
|
|||
Ok(None) => Ok(None),
|
||||
Err(e) => Err(e) } } });
|
||||
|
||||
const fn is_whitespace (c: char) -> bool { matches!(c, ' '|'\n'|'\r'|'\t') }
|
||||
pub const fn peek (mut src: &str) -> DslPerhaps<&str> {
|
||||
Ok(Some(match () {
|
||||
_ if let Ok(Some(exp)) = exp_peek(src) => exp,
|
||||
_ if let Ok(Some(sym)) = sym_peek(src) => sym,
|
||||
_ if let Ok(Some(key)) = key_peek(src) => key,
|
||||
_ if let Ok(Some(num)) = num_peek(src) => num,
|
||||
_ if let Ok(Some(text)) = text_peek(src) => text,
|
||||
_ => {
|
||||
iter_chars!(src => |_i, c| if !is_whitespace(c) {
|
||||
return Err(Unexpected(c))
|
||||
});
|
||||
return Ok(None)
|
||||
}
|
||||
}))
|
||||
}
|
||||
|
||||
pub trait DslExp: Dsl {
|
||||
fn exp (&self) -> DslPerhaps<impl DslExp> {
|
||||
todo!();
|
||||
Ok(Some(self))
|
||||
pub const fn seek (mut src: &str) -> DslPerhaps<(usize, usize)> {
|
||||
Ok(Some(match () {
|
||||
_ if let Ok(Some(exp)) = exp_seek(src) => exp,
|
||||
_ if let Ok(Some(sym)) = sym_seek(src) => sym,
|
||||
_ if let Ok(Some(key)) = key_seek(src) => key,
|
||||
_ if let Ok(Some(num)) = num_seek(src) => num,
|
||||
_ if let Ok(Some(text)) = text_seek(src) => text,
|
||||
_ => {
|
||||
iter_chars!(src => |_i, c| if !is_whitespace(c) {
|
||||
return Err(Unexpected(c))
|
||||
});
|
||||
return Ok(None)
|
||||
}
|
||||
}))
|
||||
}
|
||||
|
||||
const fn is_whitespace (c: char) -> bool { matches!(c, ' '|'\n'|'\r'|'\t') }
|
||||
pub trait DslExp<'s>: Dsl + From<&'s str> {
|
||||
fn exp (&'s self) -> DslPerhaps<Self> {
|
||||
Ok(exp_peek(self.src())?.map(Into::into))
|
||||
}
|
||||
fn exp_head (&self) -> DslPerhaps<impl Dsl> {
|
||||
todo!();
|
||||
Ok(Some(self))
|
||||
fn head (&'s self) -> DslPerhaps<Self> {
|
||||
Ok(peek(&self.src()[1..])?.map(Into::into))
|
||||
}
|
||||
fn exp_tail (&self) -> DslPerhaps<impl DslExp> {
|
||||
todo!();
|
||||
Ok(Some(self))
|
||||
}
|
||||
fn exp_next (&mut self) -> DslPerhaps<impl Dsl> {
|
||||
todo!();
|
||||
Ok(Some(self))
|
||||
fn tail (&'s self) -> DslPerhaps<Self> {
|
||||
Ok(if let Some((head_start, head_len)) = seek(&self.src()[1..])? {
|
||||
peek(&self.src()[(1+head_start+head_len)..])?.map(Into::into)
|
||||
} else {
|
||||
None
|
||||
})
|
||||
}
|
||||
}
|
||||
impl<D: Dsl> DslExp for D {}
|
||||
//impl<'s, D: DslExp<'s>> DslExp<'s> for Option<D> {}
|
||||
impl<'s, D: Dsl + From<&'s str>> DslExp<'s> for D {}
|
||||
def_peek_seek!(exp_peek, exp_seek, exp_seek_start, exp_seek_length);
|
||||
const fn is_exp_start (c: char) -> bool { matches!(c, '(') }
|
||||
const fn is_exp_end (c: char) -> bool { matches!(c, ')') }
|
||||
|
|
|
|||
|
|
@ -54,20 +54,37 @@ impl<E: Clone + Ord, C> EventMap<E, C> {
|
|||
}
|
||||
/// Create event map from string.
|
||||
pub fn from_source (source: impl AsRef<str>) -> Usually<Self> where E: From<Arc<str>> {
|
||||
Self::from_dsl(source.as_ref())
|
||||
Self::from_dsl(&mut source.as_ref())
|
||||
}
|
||||
/// Create event map from DSL tokenizer.
|
||||
pub fn from_dsl (mut dsl: impl Dsl) -> Usually<Self> where E: From<Arc<str>> {
|
||||
pub fn from_dsl <'s, D: DslExp<'s> + 's> (dsl: &'s mut D) -> Usually<Self> where E: From<Arc<str>> {
|
||||
let mut map: Self = Default::default();
|
||||
while let Some(dsl) = dsl.exp_next()? {
|
||||
if let Some(path) = dsl.text()? {
|
||||
map.0.extend(Self::from_path(PathBuf::from(path.as_ref() as &str))?.0)
|
||||
} else if dsl.exp_head()?.key()? == Some("if") {
|
||||
todo!()
|
||||
//map.add(sym.into(), Binding::from_dsl(dsl.exp_tail())?);
|
||||
} else if let Some(sym) = dsl.exp_head()?.sym()? {
|
||||
todo!()
|
||||
//map.add(sym.into(), Binding::from_dsl(dsl.exp_tail())?);
|
||||
let mut head: Option<D> = dsl.head()?;
|
||||
let mut tail: Option<D> = dsl.tail()?;
|
||||
loop {
|
||||
if let Some(ref token) = head {
|
||||
if let Some(ref text) = token.text()? {
|
||||
map.0.extend(Self::from_path(PathBuf::from(text))?.0);
|
||||
continue
|
||||
}
|
||||
//if let Some(ref exp) = token.exp()? {
|
||||
////_ if let Some(sym) = token.head()?.sym()?.as_ref() => {
|
||||
////todo!()
|
||||
////},
|
||||
////_ if Some(&"if") == token.head()?.key()?.as_ref() => {
|
||||
////todo!()
|
||||
////},
|
||||
//return Err(format!("unexpected: {:?}", token.exp()).into())
|
||||
//}
|
||||
return Err(format!("unexpected: {token:?}").into())
|
||||
} else {
|
||||
break
|
||||
}
|
||||
if let Some(next) = tail {
|
||||
head = next.head()?;
|
||||
tail = next.tail()?;
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
Ok(map)
|
||||
|
|
|
|||
|
|
@ -35,43 +35,48 @@ pub trait Input: Sized {
|
|||
}
|
||||
}
|
||||
|
||||
/// Handle input
|
||||
pub trait Handle<E: Input> {
|
||||
flex_trait_mut!(Handle <E: Input> {
|
||||
fn handle (&mut self, _input: &E) -> Perhaps<E::Handled> {
|
||||
Ok(None)
|
||||
}
|
||||
}
|
||||
impl<E: Input, H: Handle<E>> Handle<E> for &mut H {
|
||||
fn handle (&mut self, context: &E) -> Perhaps<E::Handled> {
|
||||
(*self).handle(context)
|
||||
}
|
||||
}
|
||||
impl<E: Input, H: Handle<E>> Handle<E> for Option<H> {
|
||||
fn handle (&mut self, context: &E) -> Perhaps<E::Handled> {
|
||||
if let Some(handle) = self {
|
||||
handle.handle(context)
|
||||
} else {
|
||||
Ok(None)
|
||||
}
|
||||
}
|
||||
}
|
||||
impl<H, E: Input> Handle<E> for Mutex<H> where H: Handle<E> {
|
||||
fn handle (&mut self, context: &E) -> Perhaps<E::Handled> {
|
||||
self.get_mut().unwrap().handle(context)
|
||||
}
|
||||
}
|
||||
impl<H, E: Input> Handle<E> for Arc<Mutex<H>> where H: Handle<E> {
|
||||
fn handle (&mut self, context: &E) -> Perhaps<E::Handled> {
|
||||
self.lock().unwrap().handle(context)
|
||||
}
|
||||
}
|
||||
impl<H, E: Input> Handle<E> for RwLock<H> where H: Handle<E> {
|
||||
fn handle (&mut self, context: &E) -> Perhaps<E::Handled> {
|
||||
self.write().unwrap().handle(context)
|
||||
}
|
||||
}
|
||||
impl<H, E: Input> Handle<E> for Arc<RwLock<H>> where H: Handle<E> {
|
||||
fn handle (&mut self, context: &E) -> Perhaps<E::Handled> {
|
||||
self.write().unwrap().handle(context)
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
//pub trait Handle<E: Input> {
|
||||
//fn handle (&mut self, _input: &E) -> Perhaps<E::Handled> {
|
||||
//Ok(None)
|
||||
//}
|
||||
//}
|
||||
//impl<E: Input, H: Handle<E>> Handle<E> for &mut H {
|
||||
//fn handle (&mut self, context: &E) -> Perhaps<E::Handled> {
|
||||
//(*self).handle(context)
|
||||
//}
|
||||
//}
|
||||
//impl<E: Input, H: Handle<E>> Handle<E> for Option<H> {
|
||||
//fn handle (&mut self, context: &E) -> Perhaps<E::Handled> {
|
||||
//if let Some(handle) = self {
|
||||
//handle.handle(context)
|
||||
//} else {
|
||||
//Ok(None)
|
||||
//}
|
||||
//}
|
||||
//}
|
||||
//impl<H, E: Input> Handle<E> for Mutex<H> where H: Handle<E> {
|
||||
//fn handle (&mut self, context: &E) -> Perhaps<E::Handled> {
|
||||
//self.get_mut().unwrap().handle(context)
|
||||
//}
|
||||
//}
|
||||
//impl<H, E: Input> Handle<E> for Arc<Mutex<H>> where H: Handle<E> {
|
||||
//fn handle (&mut self, context: &E) -> Perhaps<E::Handled> {
|
||||
//self.lock().unwrap().handle(context)
|
||||
//}
|
||||
//}
|
||||
//impl<H, E: Input> Handle<E> for RwLock<H> where H: Handle<E> {
|
||||
//fn handle (&mut self, context: &E) -> Perhaps<E::Handled> {
|
||||
//self.write().unwrap().handle(context)
|
||||
//}
|
||||
//}
|
||||
//impl<H, E: Input> Handle<E> for Arc<RwLock<H>> where H: Handle<E> {
|
||||
//fn handle (&mut self, context: &E) -> Perhaps<E::Handled> {
|
||||
//self.write().unwrap().handle(context)
|
||||
//}
|
||||
//}
|
||||
|
|
|
|||
|
|
@ -56,13 +56,13 @@ impl ViewDef {
|
|||
let builtins = builtins_with_boxes_output(quote! { #output })
|
||||
.map(|(builtin, builtin_ty)|match builtin {
|
||||
Single(name) => quote! {
|
||||
if dsl.exp_head()?.key()? == Some(#name) {
|
||||
if dsl.head()?.key()? == Some(#name) {
|
||||
return Ok(Some(#builtin_ty::from_dsl_or_else(self, dsl,
|
||||
||format!("failed to load builtin").into())?.boxed()))
|
||||
}
|
||||
},
|
||||
Prefix(name) => quote! {
|
||||
if let Some(key) = dsl.exp_head()?.key()? && key.starts_with(#name) {
|
||||
if let Some(key) = dsl.head()?.key()? && key.starts_with(#name) {
|
||||
return Ok(Some(#builtin_ty::from_dsl_or_else(self, dsl,
|
||||
||format!("failed to load builtin").into())?.boxed()))
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue