diff options
Diffstat (limited to 'mingling_macros/src/func')
| -rw-r--r-- | mingling_macros/src/func/dispatcher.rs | 22 | ||||
| -rw-r--r-- | mingling_macros/src/func/program_comp_gen.rs | 4 | ||||
| -rw-r--r-- | mingling_macros/src/func/program_final_gen.rs | 87 | ||||
| -rw-r--r-- | mingling_macros/src/func/register_dispatcher.rs | 20 |
4 files changed, 73 insertions, 60 deletions
diff --git a/mingling_macros/src/func/dispatcher.rs b/mingling_macros/src/func/dispatcher.rs index b5e711e..6183993 100644 --- a/mingling_macros/src/func/dispatcher.rs +++ b/mingling_macros/src/func/dispatcher.rs @@ -111,7 +111,8 @@ pub(crate) fn dispatcher(input: TokenStream) -> TokenStream { let comp_entry = get_comp_entry(&pack); - let dispatch_tree_entry = get_dispatch_tree_entry(&command_name_str, &command_struct, &pack); + let compile_time_registration = + get_compile_time_registration(&command_name_str, &command_struct, &pack); let program_type = crate::default_program_path(); @@ -129,7 +130,7 @@ pub(crate) fn dispatcher(input: TokenStream) -> TokenStream { } #comp_entry - #dispatch_tree_entry + #compile_time_registration impl ::mingling::Dispatcher<#program_type> for #command_struct { fn node(&self) -> ::mingling::Node { @@ -165,8 +166,12 @@ fn get_comp_entry(_entry_name: &Ident) -> TokenStream2 { quote! {} } -#[cfg(feature = "dispatch_tree")] -fn get_dispatch_tree_entry( +/// Registers the dispatcher at compile time (collects its node into the +/// global `COMPILE_TIME_DISPATCHERS` registry and emits the +/// `__internal_dispatcher_*` static), regardless of the `dispatch_tree` +/// feature. The feature only selects which matching strategy +/// (trie vs. linear list) is generated later by `gen_program!`. +fn get_compile_time_registration( command_name_str: &str, command_struct: &Ident, entry_name: &Ident, @@ -176,12 +181,3 @@ fn get_dispatch_tree_entry( ::mingling::macros::register_dispatcher!(#node_name_lit, #command_struct, #entry_name); } } - -#[cfg(not(feature = "dispatch_tree"))] -fn get_dispatch_tree_entry( - _command_name_str: &str, - _command_struct: &Ident, - _entry_name: &Ident, -) -> TokenStream2 { - quote! {} -} diff --git a/mingling_macros/src/func/program_comp_gen.rs b/mingling_macros/src/func/program_comp_gen.rs index d9001ad..7f77d46 100644 --- a/mingling_macros/src/func/program_comp_gen.rs +++ b/mingling_macros/src/func/program_comp_gen.rs @@ -40,14 +40,10 @@ pub(crate) fn program_comp_gen_impl(_input: TokenStream) -> TokenStream { } }; - #[cfg(feature = "dispatch_tree")] let internal_dispatcher_comp = quote! { use __internal_completion_mod::__internal_dispatcher_comp; }; - #[cfg(not(feature = "dispatch_tree"))] - let internal_dispatcher_comp = quote! {}; - let comp_dispatcher = quote! { #[doc(hidden)] mod __internal_completion_mod { diff --git a/mingling_macros/src/func/program_final_gen.rs b/mingling_macros/src/func/program_final_gen.rs index 25bca5e..d549a2b 100644 --- a/mingling_macros/src/func/program_final_gen.rs +++ b/mingling_macros/src/func/program_final_gen.rs @@ -4,7 +4,6 @@ use quote::quote; use crate::CHAINS; use crate::CHAINS_EXIST; -#[cfg(feature = "dispatch_tree")] use crate::COMPILE_TIME_DISPATCHERS; #[cfg(feature = "comp")] use crate::COMPLETIONS; @@ -16,6 +15,8 @@ use crate::RENDERERS_EXIST; #[cfg(feature = "structural_renderer")] use crate::STRUCTURAL_RENDERERS; use crate::get_global_set; +#[cfg(not(feature = "dispatch_tree"))] +use crate::systems::dispatch_list_gen; #[cfg(feature = "dispatch_tree")] use crate::systems::dispatch_tree_gen; @@ -24,6 +25,34 @@ const ASYNC_ENABLED: bool = true; #[cfg(not(feature = "async"))] const ASYNC_ENABLED: bool = false; +/// Generate the `get_nodes()` function body for a `ProgramCollect` impl. +/// +/// Shared by both dispatch strategies (trie and linear list); it only depends +/// on the compile-time-collected `__internal_dispatcher_*` statics. +fn gen_get_nodes(entries: &[(String, String, String)]) -> proc_macro2::TokenStream { + let mut node_entries = Vec::new(); + + for (node_name, _disp_type, _entry_name) in entries { + let static_name_str = format!("__internal_dispatcher_{}", just_fmt::snake_case!(node_name)); + let static_ident = + proc_macro2::Ident::new(&static_name_str, proc_macro2::Span::call_site()); + let node_display_name = node_name.replace('.', " "); + let node_display_lit = syn::LitStr::new(&node_display_name, proc_macro2::Span::call_site()); + + node_entries.push(quote! { + (#node_display_lit.to_string(), &#static_ident) + }); + } + + quote! { + fn get_nodes() -> Vec<(String, &'static (dyn ::mingling::Dispatcher<Self::Enum> + Send + Sync))> { + vec![ + #(#node_entries),* + ] + } + } +} + /// Parses an entry of the format `StructName => EnumVariant,` into a pair of idents. fn parse_entry_pair(entry: &proc_macro2::TokenStream) -> (proc_macro2::Ident, proc_macro2::Ident) { let s = entry.to_string(); @@ -117,7 +146,6 @@ pub(crate) fn program_final_gen_impl(_input: TokenStream) -> TokenStream { #[cfg(not(feature = "structural_renderer"))] let structural_render = quote! {}; - #[cfg(feature = "dispatch_tree")] let compile_time_dispatchers: Vec<String> = get_global_set(&COMPILE_TIME_DISPATCHERS) .lock() .unwrap() @@ -126,35 +154,45 @@ pub(crate) fn program_final_gen_impl(_input: TokenStream) -> TokenStream { .cloned() .collect(); - #[cfg(feature = "dispatch_tree")] - let dispatch_tree_nodes = { - let entries: Vec<(String, String, String)> = compile_time_dispatchers - .iter() - .filter_map(|entry| { - let parts: Vec<&str> = entry.split(':').collect(); - if parts.len() == 3 { - Some(( - parts[0].to_string(), - parts[1].to_string(), - parts[2].to_string(), - )) - } else { - None - } - }) - .collect(); + let entries: Vec<(String, String, String)> = compile_time_dispatchers + .iter() + .filter_map(|entry| { + let parts: Vec<&str> = entry.split(':').collect(); + if parts.len() == 3 { + Some(( + parts[0].to_string(), + parts[1].to_string(), + parts[2].to_string(), + )) + } else { + None + } + }) + .collect(); - let get_nodes_fn = dispatch_tree_gen::gen_get_nodes(&entries); - let dispatch_trie_fn = dispatch_tree_gen::gen_dispatch_args_trie(&entries); + // The `dispatch_tree` feature only selects the internal matching strategy: + // a char-level trie when enabled, a linear longest-prefix list otherwise. + #[cfg(feature = "dispatch_tree")] + let dispatch_gen = { + let get_nodes_fn = gen_get_nodes(&entries); + let dispatch_fn = dispatch_tree_gen::gen_dispatch_args_trie(&entries); quote! { #get_nodes_fn - #dispatch_trie_fn + #dispatch_fn } }; #[cfg(not(feature = "dispatch_tree"))] - let dispatch_tree_nodes = quote! {}; + let dispatch_gen = { + let get_nodes_fn = gen_get_nodes(&entries); + let dispatch_fn = dispatch_list_gen::gen_dispatch_args(&entries); + + quote! { + #get_nodes_fn + #dispatch_fn + } + }; #[cfg(feature = "comp")] let completion_tokens: Vec<proc_macro2::TokenStream> = completions @@ -367,7 +405,7 @@ pub(crate) fn program_final_gen_impl(_input: TokenStream) -> TokenStream { _ => false } } - #dispatch_tree_nodes + #dispatch_gen #structural_render #comp } @@ -395,7 +433,6 @@ pub(crate) fn program_final_gen_impl(_input: TokenStream) -> TokenStream { get_global_set(&METADATA).lock().unwrap().clear(); #[cfg(feature = "comp")] get_global_set(&COMPLETIONS).lock().unwrap().clear(); - #[cfg(feature = "dispatch_tree")] get_global_set(&COMPILE_TIME_DISPATCHERS) .lock() .unwrap() diff --git a/mingling_macros/src/func/register_dispatcher.rs b/mingling_macros/src/func/register_dispatcher.rs index eb4a6e4..dc9a31a 100644 --- a/mingling_macros/src/func/register_dispatcher.rs +++ b/mingling_macros/src/func/register_dispatcher.rs @@ -1,26 +1,19 @@ // Doc Not Optimize -#[cfg(feature = "dispatch_tree")] use just_fmt::snake_case; use proc_macro::TokenStream; use quote::quote; -#[cfg(feature = "dispatch_tree")] use syn::parse::{Parse, ParseStream}; -#[cfg(feature = "dispatch_tree")] use syn::{Ident, LitStr, Result as SynResult, Token}; -#[cfg(feature = "dispatch_tree")] use crate::COMPILE_TIME_DISPATCHERS; -#[cfg(feature = "dispatch_tree")] use crate::get_global_set; -#[cfg(feature = "dispatch_tree")] struct RegisterDispatcherInput { node_name: LitStr, dispatcher_type: Ident, entry_name: Ident, } -#[cfg(feature = "dispatch_tree")] impl Parse for RegisterDispatcherInput { fn parse(input: ParseStream) -> SynResult<Self> { let node_name: LitStr = input.parse()?; @@ -28,7 +21,7 @@ impl Parse for RegisterDispatcherInput { let dispatcher_type: Ident = input.parse()?; input.parse::<Token![,]>()?; let entry_name: Ident = input.parse()?; - Ok(RegisterDispatcherInput { + Ok(Self { node_name, dispatcher_type, entry_name, @@ -36,7 +29,6 @@ impl Parse for RegisterDispatcherInput { } } -#[cfg(feature = "dispatch_tree")] pub(crate) fn register_dispatcher(input: TokenStream) -> TokenStream { let RegisterDispatcherInput { node_name, @@ -56,10 +48,7 @@ pub(crate) fn register_dispatcher(input: TokenStream) -> TokenStream { get_global_set(&COMPILE_TIME_DISPATCHERS) .lock() .unwrap() - .insert(format!( - "{}:{}:{}", - node_name_str, dispatcher_type, entry_name - )); + .insert(format!("{node_name_str}:{dispatcher_type}:{entry_name}")); let expanded = quote! { #[doc(hidden)] @@ -69,8 +58,3 @@ pub(crate) fn register_dispatcher(input: TokenStream) -> TokenStream { expanded.into() } - -#[cfg(not(feature = "dispatch_tree"))] -pub(crate) fn register_dispatcher(_input: TokenStream) -> TokenStream { - quote! {}.into() -} |
