From 776cea6f1ba502b87bcaed3a7d794076e328df2e Mon Sep 17 00:00:00 2001 From: unspeaker Date: Wed, 21 May 2025 02:50:21 +0300 Subject: [PATCH] dsl: reduce number of lifetime arguments --- dsl/src/dsl_provide.rs | 54 ++++++++++++------------ input/src/input_dsl.rs | 16 ++++---- output/src/ops/cond.rs | 12 +++--- output/src/ops/transform.rs | 44 +++++++++++--------- proc/src/proc_command.rs | 6 +-- proc/src/proc_expose.rs | 6 +-- proc/src/proc_view.rs | 68 +++++++++++++++++-------------- tui/src/tui_content.rs | 23 ++++++----- tui/src/tui_content/tui_number.rs | 5 +++ 9 files changed, 126 insertions(+), 108 deletions(-) create mode 100644 tui/src/tui_content/tui_number.rs diff --git a/dsl/src/dsl_provide.rs b/dsl/src/dsl_provide.rs index cfb6b93..cbd99ff 100644 --- a/dsl/src/dsl_provide.rs +++ b/dsl/src/dsl_provide.rs @@ -1,30 +1,29 @@ use crate::*; -pub trait Dsl { - fn take <'state, 'source: 'state> ( - &'state self, - token: &mut TokenIter<'source> - ) - -> Perhaps; - fn take_or_fail <'state, 'source: 'state> ( - &'state self, - token: &mut TokenIter<'source>, - error: impl Into> - ) -> Usually { - if let Some(value) = Dsl::::take(self, token)? { +pub trait Dsl { + fn take <'source> (&self, token: &mut TokenIter<'source>) -> Perhaps; + fn take_or_fail <'source> ( + &self, token: &mut TokenIter<'source>, error: impl Into> + ) -> Usually { + if let Some(value) = Dsl::::take(self, token)? { Ok(value) } else { Result::Err(error.into()) } } } -pub trait Namespace<'source, State>: Sized { - fn take_from <'state> (state: &'state State, token: &mut TokenIter<'source>) + +impl, State> Dsl for State { + fn take <'source> (&self, token: &mut TokenIter<'source>) -> Perhaps { + Namespace::take_from(self, token) + } +} + +pub trait Namespace: Sized { + fn take_from <'source> (state: &State, token: &mut TokenIter<'source>) -> Perhaps; - fn take_from_or_fail <'state> ( - state: &'state State, - token: &mut TokenIter<'source>, - error: impl Into> + fn take_from_or_fail <'source> ( + state: &State, token: &mut TokenIter<'source>, error: impl Into> ) -> Usually { if let Some(value) = Namespace::::take_from(state, token)? { Ok(value) @@ -33,6 +32,7 @@ pub trait Namespace<'source, State>: Sized { } } } + //impl, T> Namespace for T { //fn take_from <'state, 'source: 'state> (state: &'state State, token: &mut TokenIter<'source>) //-> Perhaps @@ -45,9 +45,9 @@ pub trait Namespace<'source, State>: Sized { /// specifying two types and providing an expression. #[macro_export] macro_rules! from_dsl { (@a: $T:ty: |$state:ident, $words:ident|$expr:expr) => { - impl<'source, State: Dsl, A> Namespace<'source, State> for $T { - fn take_from <'state> ( - $state: &'state State, + impl, A> Namespace for $T { + fn take_from <'source> ( + $state: &State, $words: &mut TokenIter<'source>, ) -> Perhaps<$T> { $expr @@ -55,9 +55,9 @@ pub trait Namespace<'source, State>: Sized { } }; (@ab: $T:ty: |$state:ident, $words:ident|$expr:expr) => { - impl<'source, State: Dsl + Dsl, A, B> Namespace<'source, State> for $T { - fn take_from <'state> ( - $state: &'state State, + impl + Dsl, A, B> Namespace for $T { + fn take_from <'source> ( + $state: &State, $words: &mut TokenIter<'source>, ) -> Perhaps<$T> { $expr @@ -65,9 +65,9 @@ pub trait Namespace<'source, State>: Sized { } }; ($T:ty: |$state:ident:$S:ty, $words:ident|$expr:expr) => { - impl<'source> Namespace<'source, $S> for $T { - fn take_from <'state> ( - $state: &'state $S, + impl Namespace<$S> for $T { + fn take_from <'source> ( + $state: &$S, $words: &mut TokenIter<'source>, ) -> Perhaps<$T> { $expr diff --git a/input/src/input_dsl.rs b/input/src/input_dsl.rs index 29d0031..046417a 100644 --- a/input/src/input_dsl.rs +++ b/input/src/input_dsl.rs @@ -5,13 +5,13 @@ use std::marker::PhantomData; pub trait DslInput: Input { fn matches_dsl (&self, token: &str) -> bool; } /// A pre-configured mapping of input events to commands. -pub trait KeyMap<'source, S, C: Namespace<'source, S> + Command, I: DslInput> { +pub trait KeyMap<'source, S, C: Namespace + Command, I: DslInput> { /// Try to find a command that matches the current input event. fn keybind_resolve (&self, state: &S, input: &I) -> Perhaps; } /// A [SourceIter] can be a [KeyMap]. -impl<'source, S, C: Namespace<'source, S> + Command, I: DslInput> +impl<'source, S, C: Namespace + Command, I: DslInput> KeyMap<'source, S, C, I> for SourceIter<'source> { fn keybind_resolve (&self, state: &S, input: &I) -> Perhaps { @@ -40,7 +40,7 @@ for SourceIter<'source> { } /// A [TokenIter] can be a [KeyMap]. -impl<'source, S, C: Namespace<'source, S> + Command, I: DslInput> +impl<'source, S, C: Namespace + Command, I: DslInput> KeyMap<'source, S, C, I> for TokenIter<'source> { fn keybind_resolve (&self, state: &S, input: &I) -> Perhaps { @@ -74,7 +74,7 @@ pub type InputCondition<'source, S> = /// which may be made available subject to given conditions. pub struct InputMap<'source, S, - C: Command + Namespace<'source, S>, + C: Command + Namespace, I: DslInput, M: KeyMap<'source, S, C, I> > { @@ -84,7 +84,7 @@ pub struct InputMap<'source, impl<'source, S, - C: Command + Namespace<'source, S>, + C: Command + Namespace, I: DslInput, M: KeyMap<'source, S, C, I> > Default for InputMap<'source, S, C, I, M>{ @@ -95,7 +95,7 @@ impl<'source, impl<'source, S, - C: Command + Namespace<'source, S>, + C: Command + Namespace, I: DslInput, M: KeyMap<'source, S, C, I> > InputMap<'source, S, C, I, M> { @@ -122,7 +122,7 @@ impl<'source, impl<'source, S, - C: Command + Namespace<'source, S>, + C: Command + Namespace, I: DslInput, M: KeyMap<'source, S, C, I> > std::fmt::Debug for InputMap<'source, S, C, I, M> { @@ -134,7 +134,7 @@ impl<'source, /// An [InputMap] can be a [KeyMap]. impl<'source, S, - C: Command + Namespace<'source, S>, + C: Command + Namespace, I: DslInput, M: KeyMap<'source, S, C, I> > KeyMap<'source, S, C, I> for InputMap<'source, S, C, I, M> { diff --git a/output/src/ops/cond.rs b/output/src/ops/cond.rs index 67e5e16..be950fe 100644 --- a/output/src/ops/cond.rs +++ b/output/src/ops/cond.rs @@ -18,9 +18,9 @@ impl Either { } } #[cfg(feature = "dsl")] -impl<'source, A, T: Dsl + Dsl> Namespace<'source, T> for When { - fn take_from <'state> ( - state: &'state T, +impl + Dsl> Namespace for When { + fn take_from <'source> ( + state: &T, token: &mut TokenIter<'source> ) -> Perhaps { Ok(if let Some(Token { @@ -56,9 +56,9 @@ impl> Content for When { } } #[cfg(feature = "dsl")] -impl<'source, A, B, T: Dsl + Dsl + Dsl> Namespace<'source, T> for Either { - fn take_from <'state> ( - state: &'state T, +impl + Dsl + Dsl> Namespace for Either { + fn take_from <'source> ( + state: &T, token: &mut TokenIter<'source> ) -> Perhaps { if let Some(Token { value: Value::Key("either"), .. }) = token.peek() { diff --git a/output/src/ops/transform.rs b/output/src/ops/transform.rs index e5a86c4..776d95c 100644 --- a/output/src/ops/transform.rs +++ b/output/src/ops/transform.rs @@ -33,17 +33,19 @@ macro_rules! transform_xy { #[inline] pub const fn xy (item: A) -> Self { Self::XY(item) } } #[cfg(feature = "dsl")] - impl<'source, A, T: Dsl> Namespace<'source, T> for $Enum { - fn take_from <'state> (state: &'state T, iter: &mut TokenIter<'source>) -> Perhaps { - if let Some(Token { value: Value::Key(k), .. }) = iter.peek() { - let mut base = iter.clone(); - return Ok(Some(match iter.next() { + impl> Namespace for $Enum { + fn take_from <'source> ( + state: &T, token: &mut TokenIter<'source> + ) -> Perhaps { + if let Some(Token { value: Value::Key(k), .. }) = token.peek() { + let mut base = token.clone(); + return Ok(Some(match token.next() { Some(Token{value:Value::Key($x),..}) => - Self::x(state.take_or_fail(iter, "x: no content")?), + Self::x(state.take_or_fail(token, "x: no content")?), Some(Token{value:Value::Key($y),..}) => - Self::y(state.take_or_fail(iter, "y: no content")?), + Self::y(state.take_or_fail(token, "y: no content")?), Some(Token{value:Value::Key($xy),..}) => - Self::xy(state.take_or_fail(iter, "xy: no content")?), + Self::xy(state.take_or_fail(token, "xy: no content")?), _ => unreachable!() })) } @@ -77,23 +79,25 @@ macro_rules! transform_xy_unit { #[inline] pub const fn xy (x: U, y: U, item: A) -> Self { Self::XY(x, y, item) } } #[cfg(feature = "dsl")] - impl<'source, A, U: Coordinate, T: Dsl + Dsl> Namespace<'source, T> for $Enum { - fn take_from <'state> (state: &'state T, iter: &mut TokenIter<'source>) -> Perhaps { - Ok(if let Some(Token { value: Value::Key($x|$y|$xy), .. }) = iter.peek() { - let mut base = iter.clone(); - Some(match iter.next() { + impl + Dsl> Namespace for $Enum { + fn take_from <'source> ( + state: &T, token: &mut TokenIter<'source> + ) -> Perhaps { + Ok(if let Some(Token { value: Value::Key($x|$y|$xy), .. }) = token.peek() { + let mut base = token.clone(); + Some(match token.next() { Some(Token { value: Value::Key($x), .. }) => Self::x( - state.take_or_fail(iter, "x: no unit")?, - state.take_or_fail(iter, "x: no content")?, + state.take_or_fail(token, "x: no unit")?, + state.take_or_fail(token, "x: no content")?, ), Some(Token { value: Value::Key($y), .. }) => Self::y( - state.take_or_fail(iter, "y: no unit")?, - state.take_or_fail(iter, "y: no content")?, + state.take_or_fail(token, "y: no unit")?, + state.take_or_fail(token, "y: no content")?, ), Some(Token { value: Value::Key($x), .. }) => Self::xy( - state.take_or_fail(iter, "xy: no unit x")?, - state.take_or_fail(iter, "xy: no unit y")?, - state.take_or_fail(iter, "xy: no content")? + state.take_or_fail(token, "xy: no unit x")?, + state.take_or_fail(token, "xy: no unit y")?, + state.take_or_fail(token, "xy: no content")? ), _ => unreachable!(), }) diff --git a/proc/src/proc_command.rs b/proc/src/proc_command.rs index e518462..95f7a42 100644 --- a/proc/src/proc_command.rs +++ b/proc/src/proc_command.rs @@ -149,9 +149,9 @@ impl ToTokens for CommandDef { } } /// Generated by [tengri_proc::command]. - impl<'source> ::tengri::dsl::Namespace<'source, #state> for #command_enum { - fn take_from <'state> ( - state: &'state #state, + impl ::tengri::dsl::Namespace<#state> for #command_enum { + fn take_from <'source> ( + state: &#state, words: &mut ::tengri::dsl::TokenIter<'source> ) -> Perhaps { let mut words = words.clone(); diff --git a/proc/src/proc_expose.rs b/proc/src/proc_expose.rs index f3940e1..bf951b5 100644 --- a/proc/src/proc_expose.rs +++ b/proc/src/proc_expose.rs @@ -85,9 +85,9 @@ impl ToTokens for ExposeImpl { let values = variants.iter().map(ExposeArm::from); write_quote_to(out, quote! { /// Generated by [tengri_proc::expose]. - impl<'source> ::tengri::dsl::Namespace<'source, #state> for #t { - fn take_from <'state> ( - state: &'state #state, + impl ::tengri::dsl::Namespace<#state> for #t { + fn take_from <'source> ( + state: &#state, words: &mut ::tengri::dsl::TokenIter<'source> ) -> Perhaps { Ok(Some(match words.next().map(|x|x.value) { diff --git a/proc/src/proc_view.rs b/proc/src/proc_view.rs index 4e6eeb2..7223dc0 100644 --- a/proc/src/proc_view.rs +++ b/proc/src/proc_view.rs @@ -43,10 +43,15 @@ impl ToTokens for ViewDef { fn to_tokens (&self, out: &mut TokenStream2) { let Self(ViewMeta { output }, ViewImpl { block, exposed }) = self; let view = &block.self_ty; + let builtins = builtins().iter().map(|ty|write_quote(quote! { + if let Some(value) = Namespace::<#ty>::take_from(state, &mut exp.clone())? { + return Ok(Some(value.boxed())) + } + })).collect::>(); let mut available = vec![]; let exposed: Vec<_> = exposed.iter().map(|(key, value)|{ available.push(key.clone()); - write_quote(quote! { #key => Some(state.#value().boxed()), }) + write_quote(quote! { #key => Some(#view::#value(state).boxed()), }) }).collect(); let available: String = available.join(", "); let error_msg = LitStr::new( @@ -70,23 +75,26 @@ impl ToTokens for ViewDef { /// Gives [#view] the ability to construct the [Render]able /// which might corresponds to a given [TokenStream], /// while taking [#view]'s state into consideration. - impl<'source> ::tengri::dsl::Namespace<'source, #view> for Box + 'source> { - fn take_from <'state> ( - state: &'state #view, - words: &mut ::tengri::dsl::TokenIter<'source>, + impl ::tengri::dsl::Namespace<#view> for Box> { + fn take_from <'source> ( + state: &#view, + words: &mut ::tengri::dsl::TokenIter<'source> ) -> Perhaps { - Ok(words.peek().and_then(|::tengri::dsl::Token{ value, .. }|match value { - ::tengri::dsl::Value::Exp(_, exp) => { - todo!("builtin layout ops"); - //#builtins - None - }, - ::tengri::dsl::Value::Sym(sym) => match sym { - #(#exposed)* + Ok(if let Some(::tengri::dsl::Token { value, .. }) = words.peek() { + match value { + ::tengri::dsl::Value::Exp(_, exp) => { + //#(#builtins)* + None + }, + ::tengri::dsl::Value::Sym(sym) => match sym { + #(#exposed)* + _ => None + }, _ => None - }, - _ => None - })) + } + } else { + None + }) } } }) @@ -95,19 +103,19 @@ impl ToTokens for ViewDef { fn builtins () -> [TokenStream2;14] { [ - quote! { When:: }, - quote! { Either:: }, - quote! { Align:: }, - quote! { Bsp:: }, - quote! { Fill:: }, - quote! { Fixed::<_, A> }, - quote! { Min::<_, A> }, - quote! { Max::<_, A> }, - quote! { Shrink::<_, A> }, - quote! { Expand::<_, A> }, - quote! { Push::<_, A> }, - quote! { Pull::<_, A> }, - quote! { Margin::<_, A> }, - quote! { Padding::<_, A> }, + quote! { When::<_> }, + quote! { Either::<_, _> }, + quote! { Align::<_> }, + quote! { Bsp::<_, _> }, + quote! { Fill::<_> }, + quote! { Fixed::<_, _> }, + quote! { Min::<_, _> }, + quote! { Max::<_, _> }, + quote! { Shrink::<_, _> }, + quote! { Expand::<_, _> }, + quote! { Push::<_, _> }, + quote! { Pull::<_, _> }, + quote! { Margin::<_, _> }, + quote! { Padding::<_, _> }, ] } diff --git a/tui/src/tui_content.rs b/tui/src/tui_content.rs index 0d563fd..1b9cc1b 100644 --- a/tui/src/tui_content.rs +++ b/tui/src/tui_content.rs @@ -12,6 +12,18 @@ macro_rules! impl_content_layout_render { } } +mod tui_border; pub use self::tui_border::*; +mod tui_button; pub use self::tui_button::*; +mod tui_color; pub use self::tui_color::*; +mod tui_field; pub use self::tui_field::*; +mod tui_phat; pub use self::tui_phat::*; +mod tui_repeat; pub use self::tui_repeat::*; +mod tui_number; pub use self::tui_number::*; +mod tui_scroll; pub use self::tui_scroll::*; +mod tui_string; pub use self::tui_string::*; +mod tui_style; pub use self::tui_style::*; +mod tui_tryptich; pub use self::tui_tryptich::*; + impl> Content for std::sync::Arc { fn layout (&self, to: [u16;4]) -> [u16;4] { Content::::layout(&**self, to) @@ -44,14 +56,3 @@ impl> Content for Result