proc: auto implement Context on command target

Context and TryFromDsl overlap
This commit is contained in:
🪞👃🪞 2025-05-09 21:13:46 +03:00
parent 3bb38f2d27
commit 20ccff13de
5 changed files with 17 additions and 13 deletions

View file

@ -18,24 +18,20 @@ pub type ParseResult<T> = Result<T, ParseError>;
pub trait TryFromDsl<'state, T>: Sized { pub trait TryFromDsl<'state, T>: Sized {
fn try_from_expr <'source: 'state> ( fn try_from_expr <'source: 'state> (
_state: &'state T, _iter: TokenIter<'source> _state: &'state T, _iter: &mut TokenIter<'source>
) -> Option<Self> { ) -> Option<Self> {
None None
} }
fn try_from_atom <'source: 'state> ( fn try_from_atom <'source: 'state> (
state: &'state T, value: Value<'source> state: &'state T, value: Value<'source>
) -> Option<Self> { ) -> Option<Self> {
if let Exp(0, iter) = value { if let Exp(0, mut iter) = value {
return Self::try_from_expr(state, iter.clone()) return Self::try_from_expr(state, &mut iter)
} }
None None
} }
} }
pub trait TryIntoDsl<T>: Sized {
fn try_into_atom (&self) -> Option<Value>;
}
/// Map EDN tokens to parameters of a given type for a given context /// Map EDN tokens to parameters of a given type for a given context
pub trait Context<'state, U>: Sized { pub trait Context<'state, U>: Sized {
fn get <'source> (&'state self, _iter: &mut TokenIter<'source>) -> Option<U> { fn get <'source> (&'state self, _iter: &mut TokenIter<'source>) -> Option<U> {

View file

@ -29,7 +29,7 @@ impl<'state, S, C: DslCommand<'state, S>, I: DslInput> KeyMap<'state, S, C, I> f
match exp_iter.next() { match exp_iter.next() {
Some(Token { value: Value::Sym(binding), .. }) => { Some(Token { value: Value::Sym(binding), .. }) => {
if input.matches_dsl(binding) { if input.matches_dsl(binding) {
if let Some(command) = C::try_from_expr(state, exp_iter.clone()) { if let Some(command) = C::try_from_expr(state, &mut exp_iter) {
return Some(command) return Some(command)
} }
} }
@ -55,7 +55,7 @@ impl<'state, S, C: DslCommand<'state, S>, I: DslInput> KeyMap<'state, S, C, I> f
match exp_iter.next() { match exp_iter.next() {
Some(Token { value: Value::Sym(binding), .. }) => { Some(Token { value: Value::Sym(binding), .. }) => {
if input.matches_dsl(binding) { if input.matches_dsl(binding) {
if let Some(command) = C::try_from_expr(state, exp_iter.clone()) { if let Some(command) = C::try_from_expr(state, &mut exp_iter) {
return Some(command) return Some(command)
} }
} }

View file

@ -35,7 +35,7 @@ macro_rules! transform_xy {
#[cfg(feature = "dsl")] #[cfg(feature = "dsl")]
impl<'state, E: Output + 'state, T: ViewContext<'state, E>> TryFromDsl<'state, T> impl<'state, E: Output + 'state, T: ViewContext<'state, E>> TryFromDsl<'state, T>
for $Enum<RenderBox<'state, E>> { for $Enum<RenderBox<'state, E>> {
fn try_from_expr <'source: 'state> (state: &'state T, iter: TokenIter<'source>) fn try_from_expr <'source: 'state> (state: &'state T, iter: &mut TokenIter<'source>)
-> Option<Self> -> Option<Self>
{ {
let mut iter = iter.clone(); let mut iter = iter.clone();
@ -88,7 +88,7 @@ macro_rules! transform_xy_unit {
#[cfg(feature = "dsl")] #[cfg(feature = "dsl")]
impl<'state, E: Output + 'state, T: ViewContext<'state, E>> TryFromDsl<'state, T> impl<'state, E: Output + 'state, T: ViewContext<'state, E>> TryFromDsl<'state, T>
for $Enum<E::Unit, RenderBox<'state, E>> { for $Enum<E::Unit, RenderBox<'state, E>> {
fn try_from_expr <'source: 'state> (state: &'state T, iter: TokenIter<'source>) -> Option<Self> { fn try_from_expr <'source: 'state> (state: &'state T, iter: &mut TokenIter<'source>) -> Option<Self> {
let mut iter = iter.clone(); let mut iter = iter.clone();
if let Some(Token { value: Value::Key(k), .. }) = iter.peek() { if let Some(Token { value: Value::Key(k), .. }) = iter.peek() {
if k == $x || k == $y { if k == $x || k == $y {

View file

@ -103,7 +103,7 @@ pub trait ViewContext<'state, E: Output + 'state>: Send + Sync
> TryFromDsl<$lt_state, T> for $Struct { > TryFromDsl<$lt_state, T> for $Struct {
fn try_from_expr <$lt_source: $lt_state> ( fn try_from_expr <$lt_source: $lt_state> (
$state: &$lt_state T, $state: &$lt_state T,
$iter: TokenIter<$lt_source> $iter: &mut TokenIter<$lt_source>
) -> Option<Self> { ) -> Option<Self> {
let mut $iter = $iter.clone(); let mut $iter = $iter.clone();
$body; $body;

View file

@ -70,7 +70,7 @@ impl ToTokens for CommandDef {
/// Generated by [tengri_proc]. /// Generated by [tengri_proc].
impl<'state> TryFromDsl<'state, #target> for #enumeration { impl<'state> TryFromDsl<'state, #target> for #enumeration {
fn try_from_expr <'source: 'state> ( fn try_from_expr <'source: 'state> (
state: &'state #target, iter: TokenIter<'source> state: &'state #target, iter: &mut ::tengri::dsl::TokenIter<'source>
) -> Option<Self> { ) -> Option<Self> {
let mut iter = iter.clone(); let mut iter = iter.clone();
match iter.next() { match iter.next() {
@ -80,6 +80,14 @@ impl ToTokens for CommandDef {
} }
} }
/// Generated by [tengri_proc]. /// Generated by [tengri_proc].
impl<'state> ::tengri::dsl::Context<'state, #enumeration> for #target {
fn get <'source> (&self, iter: &mut ::tengri::dsl::TokenIter<'source>)
-> Option<#enumeration>
{
#enumeration::try_from_expr(self, iter)
}
}
/// Generated by [tengri_proc].
impl Command<#target> for #enumeration { impl Command<#target> for #enumeration {
fn execute (self, state: &mut #target) -> Perhaps<Self> { fn execute (self, state: &mut #target) -> Perhaps<Self> {
match self { match self {