From 809b813defcf12d7c55bf5971c962df9ebd4a694 Mon Sep 17 00:00:00 2001 From: Stephen Chung Date: Thu, 24 Dec 2020 21:28:40 +0800 Subject: [PATCH] Simplify codegen. --- codegen/src/attrs.rs | 4 +- codegen/src/function.rs | 43 ++++++++++---------- codegen/src/module.rs | 74 +++++++++++++++++------------------ codegen/src/register.rs | 1 + codegen/src/rhai_module.rs | 24 ++++++------ codegen/tests/test_modules.rs | 2 + codegen/tests/test_nested.rs | 2 +- 7 files changed, 77 insertions(+), 73 deletions(-) diff --git a/codegen/src/attrs.rs b/codegen/src/attrs.rs index a7986b6b..bd2272a4 100644 --- a/codegen/src/attrs.rs +++ b/codegen/src/attrs.rs @@ -3,7 +3,7 @@ use syn::{ spanned::Spanned, }; -#[derive(Debug)] +#[derive(Debug, Clone, Eq, PartialEq, Hash)] pub enum ExportScope { PubOnly, Prefix(String), @@ -22,12 +22,14 @@ pub trait ExportedParams: Sized { fn from_info(info: ExportInfo) -> syn::Result; } +#[derive(Debug, Clone)] pub struct AttrItem { pub key: proc_macro2::Ident, pub value: Option, pub span: proc_macro2::Span, } +#[derive(Debug, Clone)] pub struct ExportInfo { pub item_span: proc_macro2::Span, pub items: Vec, diff --git a/codegen/src/function.rs b/codegen/src/function.rs index 73c47621..426f4edc 100644 --- a/codegen/src/function.rs +++ b/codegen/src/function.rs @@ -22,23 +22,30 @@ use crate::attrs::{ExportInfo, ExportScope, ExportedParams}; #[derive(Clone, Debug, Eq, PartialEq, Copy, Hash)] pub enum FnNamespaceAccess { + Unset, Global, Internal, } -#[derive(Clone, Debug, Eq, PartialEq)] +impl Default for FnNamespaceAccess { + fn default() -> Self { + Self::Unset + } +} + +#[derive(Clone, Debug, Eq, PartialEq, Copy, Hash)] pub enum Index { Get, Set, } -#[derive(Clone, Debug, Eq, PartialEq)] +#[derive(Clone, Debug, Eq, PartialEq, Hash)] pub enum Property { Get(syn::Ident), Set(syn::Ident), } -#[derive(Clone, Debug, Eq, PartialEq)] +#[derive(Clone, Debug, Eq, PartialEq, Hash)] pub enum FnSpecialAccess { None, Index(Index), @@ -101,7 +108,7 @@ pub(crate) struct ExportedFnParams { pub return_raw: bool, pub skip: bool, pub special: FnSpecialAccess, - pub namespace: Option, + pub namespace: FnNamespaceAccess, pub span: Option, } @@ -138,7 +145,7 @@ impl ExportedParams for ExportedFnParams { let mut name = Vec::new(); let mut return_raw = false; let mut skip = false; - let mut namespace = None; + let mut namespace = FnNamespaceAccess::Unset; let mut special = FnSpecialAccess::None; for attr in attrs { let crate::attrs::AttrItem { @@ -226,22 +233,16 @@ impl ExportedParams for ExportedFnParams { ("global", Some(s)) | ("internal", Some(s)) => { return Err(syn::Error::new(s.span(), "extraneous value")) } - ("global", None) => { - if let Some(ns) = namespace { - if ns != FnNamespaceAccess::Global { - return Err(syn::Error::new(key.span(), "conflicting namespace")); - } - } - namespace = Some(FnNamespaceAccess::Global); - } - ("internal", None) => { - if let Some(ns) = namespace { - if ns != FnNamespaceAccess::Internal { - return Err(syn::Error::new(key.span(), "conflicting namespace")); - } - } - namespace = Some(FnNamespaceAccess::Internal); - } + ("global", None) => match namespace { + FnNamespaceAccess::Unset => namespace = FnNamespaceAccess::Global, + FnNamespaceAccess::Global => (), + _ => return Err(syn::Error::new(key.span(), "conflicting namespace")), + }, + ("internal", None) => match namespace { + FnNamespaceAccess::Unset => namespace = FnNamespaceAccess::Internal, + FnNamespaceAccess::Internal => (), + _ => return Err(syn::Error::new(key.span(), "conflicting namespace")), + }, (attr, _) => { return Err(syn::Error::new( key.span(), diff --git a/codegen/src/module.rs b/codegen/src/module.rs index 283436ab..de6fbd28 100644 --- a/codegen/src/module.rs +++ b/codegen/src/module.rs @@ -19,9 +19,9 @@ use std::borrow::Cow; use crate::attrs::{AttrItem, ExportInfo, ExportScope, ExportedParams}; use crate::function::ExportedFnParams; -#[derive(Debug, Default)] +#[derive(Debug, Clone, Eq, PartialEq, Hash, Default)] pub(crate) struct ExportedModParams { - pub name: Option, + pub name: String, skip: bool, pub scope: ExportScope, } @@ -49,21 +49,32 @@ impl ExportedParams for ExportedModParams { fn from_info(info: ExportInfo) -> syn::Result { let ExportInfo { items: attrs, .. } = info; - let mut name = None; + let mut name = Default::default(); let mut skip = false; - let mut scope = ExportScope::default(); + let mut scope = None; for attr in attrs { let AttrItem { key, value, .. } = attr; match (key.to_string().as_ref(), value) { - ("name", Some(s)) => name = Some(s.value()), + ("name", Some(s)) => { + let new_name = s.value(); + if name == new_name { + return Err(syn::Error::new(key.span(), "conflicting name")); + } + name = new_name; + } ("name", None) => return Err(syn::Error::new(key.span(), "requires value")), + ("skip", None) => skip = true, ("skip", Some(s)) => return Err(syn::Error::new(s.span(), "extraneous value")), - ("export_prefix", Some(s)) => scope = ExportScope::Prefix(s.value()), + + ("export_prefix", Some(_)) | ("export_all", None) if scope.is_some() => { + return Err(syn::Error::new(key.span(), "duplicate export scope")); + } + ("export_prefix", Some(s)) => scope = Some(ExportScope::Prefix(s.value())), ("export_prefix", None) => { return Err(syn::Error::new(key.span(), "requires value")) } - ("export_all", None) => scope = ExportScope::All, + ("export_all", None) => scope = Some(ExportScope::All), ("export_all", Some(s)) => { return Err(syn::Error::new(s.span(), "extraneous value")) } @@ -79,7 +90,7 @@ impl ExportedParams for ExportedModParams { Ok(ExportedModParams { name, skip, - scope, + scope: scope.unwrap_or_default(), ..Default::default() }) } @@ -87,7 +98,7 @@ impl ExportedParams for ExportedModParams { #[derive(Debug)] pub(crate) struct Module { - mod_all: Option, + mod_all: syn::ItemMod, fns: Vec, consts: Vec, submodules: Vec, @@ -183,7 +194,7 @@ impl Parse for Module { fns = new_vec![]; } Ok(Module { - mod_all: Some(mod_all), + mod_all, fns, consts, submodules, @@ -194,39 +205,27 @@ impl Parse for Module { #[allow(dead_code)] impl Module { - pub fn attrs(&self) -> Option<&Vec> { - self.mod_all.as_ref().map(|m| &m.attrs) + pub fn attrs(&self) -> &Vec { + &self.mod_all.attrs } - pub fn module_name(&self) -> Option<&syn::Ident> { - self.mod_all.as_ref().map(|m| &m.ident) + pub fn module_name(&self) -> &syn::Ident { + &self.mod_all.ident } - pub fn exported_name(&self) -> Option> { - if let Some(ref s) = self.params.name { - Some(s.into()) + pub fn exported_name(&self) -> Cow { + if !self.params.name.is_empty() { + self.params.name.as_str().into() } else { - self.module_name().map(|m| m.to_string().into()) + self.module_name().to_string().into() } } pub fn update_scope(&mut self, parent_scope: &ExportScope) { let keep = match (self.params.skip, parent_scope) { (true, _) => false, - (_, ExportScope::PubOnly) => { - if let Some(ref mod_all) = self.mod_all { - matches!(mod_all.vis, syn::Visibility::Public(_)) - } else { - false - } - } - (_, ExportScope::Prefix(s)) => { - if let Some(ref mod_all) = self.mod_all { - mod_all.ident.to_string().starts_with(s) - } else { - false - } - } + (_, ExportScope::PubOnly) => matches!(self.mod_all.vis, syn::Visibility::Public(_)), + (_, ExportScope::Prefix(s)) => self.mod_all.ident.to_string().starts_with(s), (_, ExportScope::All) => true, }; self.params.skip = !keep; @@ -249,14 +248,13 @@ impl Module { // Extract the current structure of the module. let Module { - mod_all, + mut mod_all, mut fns, consts, mut submodules, params, .. } = self; - let mut mod_all = mod_all.unwrap(); let mod_name = mod_all.ident.clone(); let (_, orig_content) = mod_all.content.take().unwrap(); let mod_attrs = mem::take(&mut mod_all.attrs); @@ -299,8 +297,8 @@ impl Module { } } - pub fn name(&self) -> Option<&syn::Ident> { - self.mod_all.as_ref().map(|m| &m.ident) + pub fn name(&self) -> &syn::Ident { + &self.mod_all.ident } pub fn consts(&self) -> &[ExportedConst] { @@ -317,10 +315,10 @@ impl Module { pub fn content(&self) -> Option<&Vec> { match self.mod_all { - Some(syn::ItemMod { + syn::ItemMod { content: Some((_, ref vec)), .. - }) => Some(vec), + } => Some(vec), _ => None, } } diff --git a/codegen/src/register.rs b/codegen/src/register.rs index 321769b7..515f13d1 100644 --- a/codegen/src/register.rs +++ b/codegen/src/register.rs @@ -18,6 +18,7 @@ pub(crate) fn generated_module_path( } type RegisterMacroInput = (syn::Expr, proc_macro2::TokenStream, syn::Path); + pub fn parse_register_macro( args: proc_macro::TokenStream, ) -> Result { diff --git a/codegen/src/rhai_module.rs b/codegen/src/rhai_module.rs index 93f47c24..5d9c148f 100644 --- a/codegen/src/rhai_module.rs +++ b/codegen/src/rhai_module.rs @@ -40,15 +40,13 @@ pub(crate) fn generate_body( if itemmod.skipped() { continue; } - let module_name = itemmod.module_name().unwrap(); - let exported_name: syn::LitStr = if let Some(name) = itemmod.exported_name() { - syn::LitStr::new(&name, proc_macro2::Span::call_site()) - } else { - syn::LitStr::new(&module_name.to_string(), proc_macro2::Span::call_site()) - }; + let module_name = itemmod.module_name(); + let exported_name: syn::LitStr = syn::LitStr::new( + itemmod.exported_name().as_ref(), + proc_macro2::Span::call_site(), + ); let cfg_attrs: Vec<&syn::Attribute> = itemmod .attrs() - .unwrap() .iter() .filter(|&a| a.path.get_ident().map(|i| *i == "cfg").unwrap_or(false)) .collect(); @@ -158,12 +156,14 @@ pub(crate) fn generate_body( } } - if let Some(ns) = function.params().namespace { - namespace = ns; + match function.params().namespace { + FnNamespaceAccess::Unset => (), + ns => namespace = ns, } let ns_str = syn::Ident::new( match namespace { + FnNamespaceAccess::Unset => unreachable!(), FnNamespaceAccess::Global => "Global", FnNamespaceAccess::Internal => "Internal", }, @@ -256,11 +256,11 @@ pub(crate) fn check_rename_collisions(fns: &Vec) -> Result<(), syn:: } for (name, fn_name) in names { - let current_span = itemfn.params().span.as_ref().unwrap(); + let current_span = itemfn.params().span.unwrap(); let key = make_key(&name, itemfn); - if let Some(other_span) = renames.insert(key, *current_span) { + if let Some(other_span) = renames.insert(key, current_span) { let mut err = syn::Error::new( - *current_span, + current_span, format!("duplicate Rhai signature for '{}'", &fn_name), ); err.combine(syn::Error::new( diff --git a/codegen/tests/test_modules.rs b/codegen/tests/test_modules.rs index 878f4fef..4c043298 100644 --- a/codegen/tests/test_modules.rs +++ b/codegen/tests/test_modules.rs @@ -291,6 +291,7 @@ fn multiple_fn_rename_test() -> Result<(), Box> { mod export_by_prefix { use rhai::plugin::*; + #[export_module(export_prefix = "foo_")] pub mod my_adds { use rhai::{FLOAT, INT}; @@ -373,6 +374,7 @@ fn export_by_prefix_test() -> Result<(), Box> { mod export_all { use rhai::plugin::*; + #[export_module(export_all)] pub mod my_adds { use rhai::{FLOAT, INT}; diff --git a/codegen/tests/test_nested.rs b/codegen/tests/test_nested.rs index cf2c1a2e..42781be1 100644 --- a/codegen/tests/test_nested.rs +++ b/codegen/tests/test_nested.rs @@ -73,8 +73,8 @@ fn one_fn_submodule_nested_attr_test() -> Result<(), Box> { mod export_nested_by_prefix { use rhai::plugin::*; - #[export_module(export_prefix = "foo_")] + #[export_module(export_prefix = "foo_")] pub mod my_adds { pub mod foo_first_adders { use rhai::{FLOAT, INT};