Compare commits

..

No commits in common. "2a6087e1c7086f09b1ade22c84ff62642df7c723" and "751e01a41e2b20561489d36ca64f9f6af6ee1f00" have entirely different histories.

3 changed files with 44 additions and 98 deletions

View file

@ -1,5 +1,5 @@
#![feature(str_as_str)]
#![feature(box_patterns)]
extern crate proc_macro;
pub(crate) use std::collections::{BTreeMap, BTreeSet};
@ -14,8 +14,7 @@ pub(crate) use syn::{
parse, parse_macro_input, parse_quote as pq,
braced, bracketed, parenthesized, Token,
Arm, Expr, Attribute, Meta, MetaList, Path, PathSegment, PathArguments,
ImplItem, ImplItemFn, LitStr, Type, ItemImpl, ReturnType, Signature, FnArg,
Pat, PatType, PatIdent,
ImplItem, ImplItemFn, LitStr, Type, ItemImpl, ReturnType, Signature, FnArg, PatType,
parse::{Parse, ParseStream, Result},
token::{PathSep, Brace},
punctuated::Punctuated,

View file

@ -57,12 +57,11 @@ impl ToTokens for CommandDef {
fn to_tokens (&self, out: &mut TokenStream2) {
let Self(CommandMeta(target), CommandImpl(block, exposed)) = self;
let enumeration = &block.self_ty;
let variants = exposed.values().map(|x|x.to_enum_variant_def());
let variants = exposed.values().map(|x|CommandArm::to_enum_variant(x, true, true, false));
let matchers = exposed.values().map(CommandArm::to_matcher);
let implementations = exposed.values().map(CommandArm::to_implementation);
write_quote_to(out, quote! {
/// Generated by [tengri_proc].
#[derive(Clone, Debug)]
pub enum #enumeration {
#(#variants)*
}
@ -86,13 +85,9 @@ impl ToTokens for CommandDef {
}
}
});
//if exposed.len() > 0 {
//panic!("{:#?}", block.self_ty);
//if let Type::Path(ref path) = *block.self_ty {
//if path.path.segments.get(0).unwrap().ident == "TekCommand" {
//panic!("\n{}", quote! {#out});
//}
//}
if exposed.len() > 0 {
//panic!("\n{}", quote! {#out});
}
}
}
@ -109,7 +104,7 @@ impl CommandArm {
fn ident_to_enum_variant (ident: &Ident) -> Arc<str> {
format!("{}", AsUpperCamelCase(format!("{ident}"))).into()
}
fn to_enum_variant_def (&self) -> TokenStream2 {
fn to_enum_variant (&self, with_types: bool, trailing_comma: bool, with_values: bool) -> TokenStream2 {
let mut out = TokenStream2::new();
out.append(self.to_enum_variant_ident());
let ident = &self.0;
@ -117,10 +112,21 @@ impl CommandArm {
out.append(Group::new(Delimiter::Brace, {
let mut out = TokenStream2::new();
for arg in self.1.iter().skip(2) {
if let FnArg::Typed(PatType {
ty, pat: box Pat::Ident(PatIdent { ident, .. }), ..
}) = arg {
write_quote_to(&mut out, quote! { #ident : #ty , });
if let FnArg::Typed(PatType { attrs, pat, colon_token, ty }) = arg {
write_quote_to(&mut out, quote! { #pat });
if with_types && with_values {
unreachable!();
}
if with_types {
write_quote_to(&mut out, quote! { : #ty });
}
if with_values {
let take_err = LitStr::new(&format!("{}: missing argument \"{}\" ({})",
quote!{#ident}, quote!{#pat}, quote!{#ty}), Span::call_site());
write_quote_to(&mut out, quote! {
: Context::get(state, &iter.next().expect(#take_err).value)
});
}
} else {
unreachable!("only typed args should be present at this position")
}
@ -128,55 +134,8 @@ impl CommandArm {
out
}));
}
out.append(Punct::new(',', Alone));
out
}
fn to_enum_variant_bind (&self) -> TokenStream2 {
let mut out = TokenStream2::new();
out.append(self.to_enum_variant_ident());
let ident = &self.0;
if self.1.len() > 2 {
out.append(Group::new(Delimiter::Brace, {
let mut out = TokenStream2::new();
for arg in self.1.iter().skip(2) {
if let FnArg::Typed(PatType {
ty, pat: box Pat::Ident(PatIdent { ident: arg, .. }), ..
}) = arg {
let take_err = LitStr::new(&format!("{}: missing argument \"{}\" ({})",
quote!{#ident}, quote!{#arg}, quote!{#ty}), Span::call_site());
let give_err = LitStr::new(&format!("{}: missing value \"{}\" ({})",
quote!{#ident}, quote!{#arg}, quote!{#ty}), Span::call_site());
write_quote_to(&mut out, quote! {
#arg : Context::get(state, &iter.next().expect(#take_err).value)
.expect(#give_err) ,
});
} else {
unreachable!("only typed args should be present at this position")
}
}
out
}));
}
out
}
fn to_enum_variant_unbind (&self) -> TokenStream2 {
let mut out = TokenStream2::new();
out.append(self.to_enum_variant_ident());
let ident = &self.0;
if self.1.len() > 2 {
out.append(Group::new(Delimiter::Brace, {
let mut out = TokenStream2::new();
for arg in self.1.iter().skip(2) {
if let FnArg::Typed(PatType {
ty, pat: box Pat::Ident(PatIdent { ident: arg, .. }), ..
}) = arg {
write_quote_to(&mut out, quote! { #arg , });
} else {
unreachable!("only typed args should be present at this position")
}
}
out
}));
if trailing_comma {
out.append(Punct::new(',', Alone));
}
out
}
@ -185,13 +144,11 @@ impl CommandArm {
let key = LitStr::new(&self.to_key(), Span::call_site());
let ident = &self.0;
let take_args = self.1.iter().skip(2).map(|arg|{
if let FnArg::Typed(PatType {
ty, pat: box Pat::Ident(PatIdent { ident: arg, .. }), ..
}) = arg {
if let FnArg::Typed(PatType { attrs, pat, colon_token, ty }) = arg {
let take_err = LitStr::new(&format!("{}: missing argument \"{}\" ({})",
quote!{#ident}, quote!{#arg}, quote!{#ty}), Span::call_site());
quote!{#ident}, quote!{#pat}, quote!{#ty}), Span::call_site());
write_quote(quote! {
let #ident: #ty = Context::<#ty>::get(
let #pat: #ty = Context::<#ty>::get(
state,
&iter.next().expect(#take_err).value
);
@ -201,7 +158,7 @@ impl CommandArm {
}
}).collect::<Vec<_>>();
let variant = Self::ident_to_enum_variant(&self.0);
let variant = self.to_enum_variant_bind();
let variant = self.to_enum_variant(false, false, true);
write_quote(quote! {
Some(::tengri::dsl::Token { value: ::tengri::dsl::Value::Key(#key), .. }) => {
let mut iter = iter.clone();
@ -213,15 +170,13 @@ impl CommandArm {
}
fn to_implementation (&self) -> TokenStream2 {
let ident = &self.0;
let variant = self.to_enum_variant_unbind();
let mut give_rest = write_quote(quote! { /*TODO*/ });
let variant = self.to_enum_variant(false, false, false);
let mut give_rest = write_quote(quote! { });
let give_args = self.1.iter().skip(2).map(|arg|{
if let FnArg::Typed(PatType {
ty, pat: box Pat::Ident(PatIdent { ident: arg, .. }), ..
}) = arg {
if let FnArg::Typed(PatType { attrs, pat, colon_token, ty }) = arg {
//let give_err = LitStr::new(&format!("{}: missing value \"{}\" ({})",
//quote!{#ident}, quote!{#pat}, quote!{#ty}), Span::call_site());
write_quote(quote! { #arg, })
write_quote(quote! { #pat, })
} else {
unreachable!("only typed args should be present at this position")
}

View file

@ -70,31 +70,23 @@ impl ToTokens for ExposeImpl {
out.append(token);
}
for (t, variants) in exposed.iter() {
let formatted_type = format!("{}", quote! { #t });
let predefined = match formatted_type.as_str() {
"bool" => quote! {
::tengri::dsl::Value::Sym(":true") => true,
::tengri::dsl::Value::Sym(":false") => false,
},
let predefined = match format!("{}", quote! { #t }).as_str() {
"bool" => vec![
quote! { ::tengri::dsl::Value::Sym(":true") => true },
quote! { ::tengri::dsl::Value::Sym(":false") => false },
],
"u8" | "u16" | "u32" | "u64" | "usize" |
"i8" | "i16" | "i32" | "i64" | "isize" => {
let num_err = LitStr::new(
&format!("{{n}}: failed to convert to {formatted_type}"),
Span::call_site()
);
quote! {
::tengri::dsl::Value::Num(n) => TryInto::<#t>::try_into(*n)
.unwrap_or_else(|_|panic!(#num_err)),
}
},
_ => quote! {},
"i8" | "i16" | "i32" | "i64" | "isize" => vec![
quote! { ::tengri::dsl::Value::Num(n) => *n },
],
_ => vec![],
};
let values = variants.iter().map(|(k, v)|ExposeArm(k.clone(), v.clone()));
let trait_impl = quote! {
impl ::tengri::dsl::Context<#t> for #target {
fn get (&self, dsl: &::tengri::dsl::Value) -> Option<#t> {
Some(match dsl {
#predefined
#(#predefined,)*
#(#values,)*
_ => return None
})
@ -105,9 +97,9 @@ impl ToTokens for ExposeImpl {
out.append(token);
}
}
if exposed.len() > 0 {
//if exposed.len() > 0 {
//panic!("{}", quote! {#out});
}
//}
}
}