aboutsummaryrefslogtreecommitdiff
path: root/mingling_macros/src/func
diff options
context:
space:
mode:
Diffstat (limited to 'mingling_macros/src/func')
-rw-r--r--mingling_macros/src/func/dispatcher.rs22
-rw-r--r--mingling_macros/src/func/program_comp_gen.rs4
-rw-r--r--mingling_macros/src/func/program_final_gen.rs87
-rw-r--r--mingling_macros/src/func/register_dispatcher.rs20
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()
-}