diff --git a/core/src/core_macros.rs b/core/src/core_macros.rs new file mode 100644 index 0000000..b819764 --- /dev/null +++ b/core/src/core_macros.rs @@ -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 } };); diff --git a/core/src/lib.rs b/core/src/lib.rs index b06b55e..0c63c05 100644 --- a/core/src/lib.rs +++ b/core/src/lib.rs @@ -1,38 +1,13 @@ +mod core_macros; pub(crate) use std::error::Error; /// Standard result type. pub type Usually = Result>; /// Standard optional result type. pub type Perhaps = Result, Box>; -/// 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: 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: 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 { /// A custom operation on [Args] that may return [Result::Err] or [Option::None]. diff --git a/dsl/src/dsl.rs b/dsl/src/dsl.rs index 530e4f5..8f83589 100644 --- a/dsl/src/dsl.rs +++ b/dsl/src/dsl.rs @@ -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 { fn src (&self) -> &str { self.as_ref() } } -impl Dsl for Option { - fn src (&self) -> &str { if let Some(dsl) = self { dsl.src() } else { "" } } -} - impl Dsl for &D { fn src (&self) -> &str { (*self).src() } } @@ -43,6 +40,14 @@ impl Dsl for &mut D { fn src (&self) -> &str { (**self).src() } } +impl Dsl for std::sync::Arc { + fn src (&self) -> &str { (*self).src() } +} + +impl Dsl for Option { + fn src (&self) -> &str { if let Some(dsl) = self { dsl.src() } else { "" } } +} + /// DSL-specific result type. pub type DslResult = Result; diff --git a/dsl/src/dsl_types.rs b/dsl/src/dsl_types.rs index 0a5402d..c9d69a1 100644 --- a/dsl/src/dsl_types.rs +++ b/dsl/src/dsl_types.rs @@ -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 { - 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 { + Ok(exp_peek(self.src())?.map(Into::into)) } - fn exp_head (&self) -> DslPerhaps { - todo!(); - Ok(Some(self)) + fn head (&'s self) -> DslPerhaps { + Ok(peek(&self.src()[1..])?.map(Into::into)) } - fn exp_tail (&self) -> DslPerhaps { - todo!(); - Ok(Some(self)) - } - fn exp_next (&mut self) -> DslPerhaps { - todo!(); - Ok(Some(self)) + fn tail (&'s self) -> DslPerhaps { + 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 DslExp for D {} +//impl<'s, D: DslExp<'s>> DslExp<'s> for Option {} +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, ')') } diff --git a/input/src/input_dsl.rs b/input/src/input_dsl.rs index 0bec9a8..8e87506 100644 --- a/input/src/input_dsl.rs +++ b/input/src/input_dsl.rs @@ -54,20 +54,37 @@ impl EventMap { } /// Create event map from string. pub fn from_source (source: impl AsRef) -> Usually where E: From> { - 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 where E: From> { + pub fn from_dsl <'s, D: DslExp<'s> + 's> (dsl: &'s mut D) -> Usually where E: From> { 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 = dsl.head()?; + let mut tail: Option = 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) diff --git a/input/src/input_handle.rs b/input/src/input_handle.rs index 2be276c..ed13cdc 100644 --- a/input/src/input_handle.rs +++ b/input/src/input_handle.rs @@ -35,43 +35,48 @@ pub trait Input: Sized { } } -/// Handle input -pub trait Handle { +flex_trait_mut!(Handle { fn handle (&mut self, _input: &E) -> Perhaps { Ok(None) } -} -impl> Handle for &mut H { - fn handle (&mut self, context: &E) -> Perhaps { - (*self).handle(context) - } -} -impl> Handle for Option { - fn handle (&mut self, context: &E) -> Perhaps { - if let Some(handle) = self { - handle.handle(context) - } else { - Ok(None) - } - } -} -impl Handle for Mutex where H: Handle { - fn handle (&mut self, context: &E) -> Perhaps { - self.get_mut().unwrap().handle(context) - } -} -impl Handle for Arc> where H: Handle { - fn handle (&mut self, context: &E) -> Perhaps { - self.lock().unwrap().handle(context) - } -} -impl Handle for RwLock where H: Handle { - fn handle (&mut self, context: &E) -> Perhaps { - self.write().unwrap().handle(context) - } -} -impl Handle for Arc> where H: Handle { - fn handle (&mut self, context: &E) -> Perhaps { - self.write().unwrap().handle(context) - } -} +}); + +//pub trait Handle { + //fn handle (&mut self, _input: &E) -> Perhaps { + //Ok(None) + //} +//} +//impl> Handle for &mut H { + //fn handle (&mut self, context: &E) -> Perhaps { + //(*self).handle(context) + //} +//} +//impl> Handle for Option { + //fn handle (&mut self, context: &E) -> Perhaps { + //if let Some(handle) = self { + //handle.handle(context) + //} else { + //Ok(None) + //} + //} +//} +//impl Handle for Mutex where H: Handle { + //fn handle (&mut self, context: &E) -> Perhaps { + //self.get_mut().unwrap().handle(context) + //} +//} +//impl Handle for Arc> where H: Handle { + //fn handle (&mut self, context: &E) -> Perhaps { + //self.lock().unwrap().handle(context) + //} +//} +//impl Handle for RwLock where H: Handle { + //fn handle (&mut self, context: &E) -> Perhaps { + //self.write().unwrap().handle(context) + //} +//} +//impl Handle for Arc> where H: Handle { + //fn handle (&mut self, context: &E) -> Perhaps { + //self.write().unwrap().handle(context) + //} +//} diff --git a/proc/src/proc_view.rs b/proc/src/proc_view.rs index bd44c96..13a5d5c 100644 --- a/proc/src/proc_view.rs +++ b/proc/src/proc_view.rs @@ -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())) }