From 4abbb0fb142029e7abd215f294880aa9aaa5d282 Mon Sep 17 00:00:00 2001 From: Soares Chen Date: Sun, 17 May 2026 20:38:50 +0200 Subject: [PATCH 01/81] Scaffold cgp-macro-core crate --- Cargo.lock | 9 +++++++++ Cargo.toml | 2 ++ crates/cgp-macro-core/Cargo.toml | 20 ++++++++++++++++++++ crates/cgp-macro-core/src/lib.rs | 1 + crates/cgp-macro-core/src/types/mod.rs | 1 + 5 files changed, 33 insertions(+) create mode 100644 crates/cgp-macro-core/Cargo.toml create mode 100644 crates/cgp-macro-core/src/lib.rs create mode 100644 crates/cgp-macro-core/src/types/mod.rs diff --git a/Cargo.lock b/Cargo.lock index bd3a639d..4e24e82d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -153,6 +153,15 @@ dependencies = [ "syn", ] +[[package]] +name = "cgp-macro-core" +version = "0.7.0" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "cgp-macro-lib" version = "0.7.0" diff --git a/Cargo.toml b/Cargo.toml index cd6f5bd9..4c581260 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,6 +9,7 @@ members = [ "crates/cgp-async-macro", "crates/cgp-component", "crates/cgp-macro", + "crates/cgp-macro-core", "crates/cgp-macro-lib", "crates/cgp-type", "crates/cgp-field", @@ -50,6 +51,7 @@ cgp-field-extra = { version = "0.7.0", path = "./crates/cgp-field-ex cgp-error = { version = "0.7.0", path = "./crates/cgp-error" } cgp-error-extra = { version = "0.7.0", path = "./crates/cgp-error-extra" } cgp-extra-macro = { version = "0.7.0", path = "./crates/cgp-extra-macro" } +cgp-extra-macro-core = { version = "0.7.0", path = "./crates/cgp-extra-macro-lib" } cgp-extra-macro-lib = { version = "0.7.0", path = "./crates/cgp-extra-macro-lib" } cgp-handler = { version = "0.7.0", path = "./crates/cgp-handler" } cgp-monad = { version = "0.7.0", path = "./crates/cgp-monad" } diff --git a/crates/cgp-macro-core/Cargo.toml b/crates/cgp-macro-core/Cargo.toml new file mode 100644 index 00000000..ef93dd8a --- /dev/null +++ b/crates/cgp-macro-core/Cargo.toml @@ -0,0 +1,20 @@ +[package] +name = "cgp-macro-core" +version = "0.7.0" +edition = { workspace = true } +license = { workspace = true } +repository = { workspace = true } +authors = { workspace = true } +rust-version = { workspace = true } +keywords = { workspace = true } +description = """ + Context-generic programming core component macros implemented as a library. +""" + +[features] +default = [] + +[dependencies] +syn = { version = "2.0.95", features = [ "full", "extra-traits", "visit", "visit-mut" ] } +quote = "1.0.38" +proc-macro2 = "1.0.92" diff --git a/crates/cgp-macro-core/src/lib.rs b/crates/cgp-macro-core/src/lib.rs new file mode 100644 index 00000000..cd408564 --- /dev/null +++ b/crates/cgp-macro-core/src/lib.rs @@ -0,0 +1 @@ +pub mod types; diff --git a/crates/cgp-macro-core/src/types/mod.rs b/crates/cgp-macro-core/src/types/mod.rs new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/crates/cgp-macro-core/src/types/mod.rs @@ -0,0 +1 @@ + From 92171d0ecb80fec172de3f556cccd337d4b0e35d Mon Sep 17 00:00:00 2001 From: Soares Chen Date: Sun, 17 May 2026 21:23:47 +0200 Subject: [PATCH 02/81] Scaffold Symbol impls --- crates/cgp-macro-core/src/exports.rs | 8 ++++ crates/cgp-macro-core/src/lib.rs | 5 +++ crates/cgp-macro-core/src/macros.rs | 14 +++++++ crates/cgp-macro-core/src/traits/mod.rs | 3 ++ crates/cgp-macro-core/src/traits/to_type.rs | 5 +++ crates/cgp-macro-core/src/types/mod.rs | 3 +- crates/cgp-macro-core/src/types/path/mod.rs | 5 +++ .../src/types/path/path_element.rs | 24 +++++++++++ .../cgp-macro-core/src/types/path/unipath.rs | 1 + crates/cgp-macro-core/src/types/symbol.rs | 41 +++++++++++++++++++ 10 files changed, 108 insertions(+), 1 deletion(-) create mode 100644 crates/cgp-macro-core/src/exports.rs create mode 100644 crates/cgp-macro-core/src/macros.rs create mode 100644 crates/cgp-macro-core/src/traits/mod.rs create mode 100644 crates/cgp-macro-core/src/traits/to_type.rs create mode 100644 crates/cgp-macro-core/src/types/path/mod.rs create mode 100644 crates/cgp-macro-core/src/types/path/path_element.rs create mode 100644 crates/cgp-macro-core/src/types/path/unipath.rs create mode 100644 crates/cgp-macro-core/src/types/symbol.rs diff --git a/crates/cgp-macro-core/src/exports.rs b/crates/cgp-macro-core/src/exports.rs new file mode 100644 index 00000000..9f399223 --- /dev/null +++ b/crates/cgp-macro-core/src/exports.rs @@ -0,0 +1,8 @@ +use crate::export_constructs; + +export_constructs! { + Nil => ε, + Cons => π, + Chars => ζ, + Symbol => ψ, +} diff --git a/crates/cgp-macro-core/src/lib.rs b/crates/cgp-macro-core/src/lib.rs index cd408564..a5b7d4ff 100644 --- a/crates/cgp-macro-core/src/lib.rs +++ b/crates/cgp-macro-core/src/lib.rs @@ -1 +1,6 @@ +#![allow(mixed_script_confusables)] + +pub mod exports; +pub mod macros; +pub mod traits; pub mod types; diff --git a/crates/cgp-macro-core/src/macros.rs b/crates/cgp-macro-core/src/macros.rs new file mode 100644 index 00000000..e0b70634 --- /dev/null +++ b/crates/cgp-macro-core/src/macros.rs @@ -0,0 +1,14 @@ +#[macro_export] +macro_rules! export_constructs { + ( $( $from:ident => $to:ident ),* $(,)? ) => { + $( + pub struct $from; + + impl ::quote::ToTokens for $from { + fn to_tokens(&self, tokens: &mut ::proc_macro2::TokenStream) { + tokens.extend(::quote::quote! { ::cgp::macro_prelude::$to }) + } + } + )* + }; +} diff --git a/crates/cgp-macro-core/src/traits/mod.rs b/crates/cgp-macro-core/src/traits/mod.rs new file mode 100644 index 00000000..b15bcc24 --- /dev/null +++ b/crates/cgp-macro-core/src/traits/mod.rs @@ -0,0 +1,3 @@ +mod to_type; + +pub use to_type::*; diff --git a/crates/cgp-macro-core/src/traits/to_type.rs b/crates/cgp-macro-core/src/traits/to_type.rs new file mode 100644 index 00000000..f11eb2a4 --- /dev/null +++ b/crates/cgp-macro-core/src/traits/to_type.rs @@ -0,0 +1,5 @@ +use syn::Type; + +pub trait ToType { + fn to_type(&self) -> Type; +} diff --git a/crates/cgp-macro-core/src/types/mod.rs b/crates/cgp-macro-core/src/types/mod.rs index 8b137891..c21b6234 100644 --- a/crates/cgp-macro-core/src/types/mod.rs +++ b/crates/cgp-macro-core/src/types/mod.rs @@ -1 +1,2 @@ - +pub mod path; +pub mod symbol; diff --git a/crates/cgp-macro-core/src/types/path/mod.rs b/crates/cgp-macro-core/src/types/path/mod.rs new file mode 100644 index 00000000..5ef6775f --- /dev/null +++ b/crates/cgp-macro-core/src/types/path/mod.rs @@ -0,0 +1,5 @@ +mod path_element; +mod unipath; + +pub use path_element::*; +pub use unipath::*; diff --git a/crates/cgp-macro-core/src/types/path/path_element.rs b/crates/cgp-macro-core/src/types/path/path_element.rs new file mode 100644 index 00000000..4bb375c1 --- /dev/null +++ b/crates/cgp-macro-core/src/types/path/path_element.rs @@ -0,0 +1,24 @@ +use quote::ToTokens; +use syn::parse::{Parse, ParseStream}; +use syn::{Ident, Type, parse2}; + +use crate::types::symbol::Symbol; + +pub enum PathElement { + Type(Type), + Symbol(Symbol), +} + +impl Parse for PathElement { + fn parse(input: ParseStream) -> syn::Result { + let ty: Type = input.parse()?; + + let parsed = if let Ok(ident) = parse2::(ty.to_token_stream()) { + Self::Symbol(Symbol { ident }) + } else { + Self::Type(ty) + }; + + Ok(parsed) + } +} diff --git a/crates/cgp-macro-core/src/types/path/unipath.rs b/crates/cgp-macro-core/src/types/path/unipath.rs new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/crates/cgp-macro-core/src/types/path/unipath.rs @@ -0,0 +1 @@ + diff --git a/crates/cgp-macro-core/src/types/symbol.rs b/crates/cgp-macro-core/src/types/symbol.rs new file mode 100644 index 00000000..b6f51ddb --- /dev/null +++ b/crates/cgp-macro-core/src/types/symbol.rs @@ -0,0 +1,41 @@ +use proc_macro2::{Literal, TokenStream}; +use quote::{ToTokens, quote_spanned}; +use syn::{Ident, Type, parse_quote}; + +use crate::traits::ToType; + +pub struct Symbol { + pub ident: Ident, +} + +impl Symbol { + pub fn new(ident: Ident) -> Self { + Self { ident } + } +} + +impl ToTokens for Symbol { + fn to_tokens(&self, tokens: &mut TokenStream) { + use crate::exports::{Chars, Nil, Symbol}; + + let span = self.ident.span(); + let str_value = self.ident.to_string(); + + let chars = str_value.chars().rev().fold( + quote_spanned!(span => #Nil), + |acc, current| quote_spanned!(span => #Chars < #current, #acc >), + ); + + let len = Literal::usize_unsuffixed(str_value.len()); + + let out = quote_spanned! { span => #Symbol < #len, #chars > }; + + tokens.extend(out); + } +} + +impl ToType for Symbol { + fn to_type(&self) -> Type { + parse_quote!( #self ) + } +} From 02d96af2a5b091877dc7c6c4cecc6d18ee7bd84e Mon Sep 17 00:00:00 2001 From: Soares Chen Date: Sun, 17 May 2026 21:37:34 +0200 Subject: [PATCH 03/81] Implement UniPath --- crates/cgp-macro-core/src/exports.rs | 2 ++ crates/cgp-macro-core/src/macros.rs | 26 ++++++++++------ .../src/types/path/path_element.rs | 20 +++++++++++++ .../cgp-macro-core/src/types/path/unipath.rs | 30 +++++++++++++++++++ 4 files changed, 69 insertions(+), 9 deletions(-) diff --git a/crates/cgp-macro-core/src/exports.rs b/crates/cgp-macro-core/src/exports.rs index 9f399223..0bbec9d6 100644 --- a/crates/cgp-macro-core/src/exports.rs +++ b/crates/cgp-macro-core/src/exports.rs @@ -5,4 +5,6 @@ export_constructs! { Cons => π, Chars => ζ, Symbol => ψ, + PathCons, + PathNil, } diff --git a/crates/cgp-macro-core/src/macros.rs b/crates/cgp-macro-core/src/macros.rs index e0b70634..02db7ff4 100644 --- a/crates/cgp-macro-core/src/macros.rs +++ b/crates/cgp-macro-core/src/macros.rs @@ -1,14 +1,22 @@ #[macro_export] -macro_rules! export_constructs { - ( $( $from:ident => $to:ident ),* $(,)? ) => { - $( - pub struct $from; +macro_rules! export_construct { + ( $from:ident => $to:ident ) => { + pub struct $from; - impl ::quote::ToTokens for $from { - fn to_tokens(&self, tokens: &mut ::proc_macro2::TokenStream) { - tokens.extend(::quote::quote! { ::cgp::macro_prelude::$to }) - } + impl ::quote::ToTokens for $from { + fn to_tokens(&self, tokens: &mut ::proc_macro2::TokenStream) { + tokens.extend(::quote::quote! { ::cgp::macro_prelude::$to }) } - )* + } + }; + ( $ident:ident ) => { + $crate::export_construct! { $ident => $ident } + }; +} + +#[macro_export] +macro_rules! export_constructs { + ( $( $from:ident $( => $to:ident )? ),* $(,)? ) => { + $( $crate::export_construct! { $from $( => $to )* } )* }; } diff --git a/crates/cgp-macro-core/src/types/path/path_element.rs b/crates/cgp-macro-core/src/types/path/path_element.rs index 4bb375c1..8aebd408 100644 --- a/crates/cgp-macro-core/src/types/path/path_element.rs +++ b/crates/cgp-macro-core/src/types/path/path_element.rs @@ -1,7 +1,9 @@ +use proc_macro2::TokenStream; use quote::ToTokens; use syn::parse::{Parse, ParseStream}; use syn::{Ident, Type, parse2}; +use crate::traits::ToType; use crate::types::symbol::Symbol; pub enum PathElement { @@ -22,3 +24,21 @@ impl Parse for PathElement { Ok(parsed) } } + +impl ToType for PathElement { + fn to_type(&self) -> Type { + match self { + Self::Type(ty) => ty.clone(), + Self::Symbol(symbol) => symbol.to_type(), + } + } +} + +impl ToTokens for PathElement { + fn to_tokens(&self, tokens: &mut TokenStream) { + match self { + Self::Type(ty) => ty.to_tokens(tokens), + Self::Symbol(symbol) => symbol.to_tokens(tokens), + } + } +} diff --git a/crates/cgp-macro-core/src/types/path/unipath.rs b/crates/cgp-macro-core/src/types/path/unipath.rs index 8b137891..dfdac90b 100644 --- a/crates/cgp-macro-core/src/types/path/unipath.rs +++ b/crates/cgp-macro-core/src/types/path/unipath.rs @@ -1 +1,31 @@ +use proc_macro2::TokenStream; +use quote::{ToTokens, quote}; +use syn::parse::{Parse, ParseStream}; +use syn::punctuated::Punctuated; +use syn::token::Dot; +use crate::exports::{PathCons, PathNil}; +use crate::types::path::PathElement; + +pub struct UniPath { + pub elements: Punctuated, +} + +impl Parse for UniPath { + fn parse(input: ParseStream) -> syn::Result { + let elements = Punctuated::parse_terminated(input)?; + + Ok(Self { elements }) + } +} + +impl ToTokens for UniPath { + fn to_tokens(&self, tokens: &mut TokenStream) { + let out = self.elements.iter().rev().fold( + quote!(#PathNil), + |acc, current| quote!( #PathCons < #current, #acc > ), + ); + + tokens.extend(out) + } +} From 605bba0b2185840055e9b1435f3b01bd3f00c8c8 Mon Sep 17 00:00:00 2001 From: Soares Chen Date: Sun, 17 May 2026 21:52:08 +0200 Subject: [PATCH 04/81] Use UniPath in UseNamespaceAttribute --- Cargo.lock | 1 + Cargo.toml | 2 +- crates/cgp-macro-core/src/macros.rs | 2 +- .../src/types/path/path_element.rs | 26 +++++++++++++++++-- .../cgp-macro-core/src/types/path/unipath.rs | 11 +++++++- crates/cgp-macro-lib/Cargo.toml | 2 ++ .../cgp-macro-lib/src/attributes/namespace.rs | 22 ++++------------ crates/cgp/src/lib.rs | 2 ++ 8 files changed, 46 insertions(+), 22 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 4e24e82d..e69dc313 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -166,6 +166,7 @@ dependencies = [ name = "cgp-macro-lib" version = "0.7.0" dependencies = [ + "cgp-macro-core", "itertools", "prettyplease", "proc-macro2", diff --git a/Cargo.toml b/Cargo.toml index 4c581260..043c269e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -44,6 +44,7 @@ cgp-extra = { version = "0.7.0", path = "./crates/cgp-extra" } cgp-async-macro = { version = "0.7.0", path = "./crates/cgp-async-macro" } cgp-component = { version = "0.7.0", path = "./crates/cgp-component" } cgp-macro = { version = "0.7.0", path = "./crates/cgp-macro" } +cgp-macro-core = { version = "0.7.0", path = "./crates/cgp-macro-core" } cgp-macro-lib = { version = "0.7.0", path = "./crates/cgp-macro-lib" } cgp-type = { version = "0.7.0", path = "./crates/cgp-type" } cgp-field = { version = "0.7.0", path = "./crates/cgp-field" } @@ -51,7 +52,6 @@ cgp-field-extra = { version = "0.7.0", path = "./crates/cgp-field-ex cgp-error = { version = "0.7.0", path = "./crates/cgp-error" } cgp-error-extra = { version = "0.7.0", path = "./crates/cgp-error-extra" } cgp-extra-macro = { version = "0.7.0", path = "./crates/cgp-extra-macro" } -cgp-extra-macro-core = { version = "0.7.0", path = "./crates/cgp-extra-macro-lib" } cgp-extra-macro-lib = { version = "0.7.0", path = "./crates/cgp-extra-macro-lib" } cgp-handler = { version = "0.7.0", path = "./crates/cgp-handler" } cgp-monad = { version = "0.7.0", path = "./crates/cgp-monad" } diff --git a/crates/cgp-macro-core/src/macros.rs b/crates/cgp-macro-core/src/macros.rs index 02db7ff4..fb77383f 100644 --- a/crates/cgp-macro-core/src/macros.rs +++ b/crates/cgp-macro-core/src/macros.rs @@ -5,7 +5,7 @@ macro_rules! export_construct { impl ::quote::ToTokens for $from { fn to_tokens(&self, tokens: &mut ::proc_macro2::TokenStream) { - tokens.extend(::quote::quote! { ::cgp::macro_prelude::$to }) + tokens.extend(::quote::quote! { $to }) } } }; diff --git a/crates/cgp-macro-core/src/types/path/path_element.rs b/crates/cgp-macro-core/src/types/path/path_element.rs index 8aebd408..a8ff04e9 100644 --- a/crates/cgp-macro-core/src/types/path/path_element.rs +++ b/crates/cgp-macro-core/src/types/path/path_element.rs @@ -15,8 +15,16 @@ impl Parse for PathElement { fn parse(input: ParseStream) -> syn::Result { let ty: Type = input.parse()?; - let parsed = if let Ok(ident) = parse2::(ty.to_token_stream()) { - Self::Symbol(Symbol { ident }) + let parsed = if let Ok(path_ident) = parse2::(ty.to_token_stream()) { + let path_str = path_ident.to_string(); + if let Some(path_char) = path_str.chars().next() + && path_char.is_ascii_lowercase() + && !is_primitive_type(&path_str) + { + Self::Symbol(Symbol { ident: path_ident }) + } else { + Self::Type(ty) + } } else { Self::Type(ty) }; @@ -42,3 +50,17 @@ impl ToTokens for PathElement { } } } + +pub fn is_primitive_type(ident: &str) -> bool { + if (ident.starts_with("i") || ident.starts_with("u") || ident.starts_with("f")) + && ident[1..].chars().all(|c| c.is_numeric()) + { + return true; + } + + if ["char", "bool", "usize", "isize", "str"].contains(&ident) { + return true; + } + + false +} diff --git a/crates/cgp-macro-core/src/types/path/unipath.rs b/crates/cgp-macro-core/src/types/path/unipath.rs index dfdac90b..d4afbbda 100644 --- a/crates/cgp-macro-core/src/types/path/unipath.rs +++ b/crates/cgp-macro-core/src/types/path/unipath.rs @@ -1,8 +1,9 @@ use proc_macro2::TokenStream; use quote::{ToTokens, quote}; +use syn::Type; use syn::parse::{Parse, ParseStream}; use syn::punctuated::Punctuated; -use syn::token::Dot; +use syn::token::{At, Dot}; use crate::exports::{PathCons, PathNil}; use crate::types::path::PathElement; @@ -11,8 +12,16 @@ pub struct UniPath { pub elements: Punctuated, } +impl UniPath { + pub fn append_type(&mut self, ty: Type) { + self.elements.push(PathElement::Type(ty)); + } +} + impl Parse for UniPath { fn parse(input: ParseStream) -> syn::Result { + let _: At = input.parse()?; + let elements = Punctuated::parse_terminated(input)?; Ok(Self { elements }) diff --git a/crates/cgp-macro-lib/Cargo.toml b/crates/cgp-macro-lib/Cargo.toml index a490a0e0..44e48059 100644 --- a/crates/cgp-macro-lib/Cargo.toml +++ b/crates/cgp-macro-lib/Cargo.toml @@ -15,6 +15,8 @@ description = """ default = [] [dependencies] +cgp-macro-core = { workspace = true } + syn = { version = "2.0.95", features = [ "full", "extra-traits", "visit", "visit-mut" ] } quote = "1.0.38" proc-macro2 = "1.0.92" diff --git a/crates/cgp-macro-lib/src/attributes/namespace.rs b/crates/cgp-macro-lib/src/attributes/namespace.rs index ef142a5d..b57f94d5 100644 --- a/crates/cgp-macro-lib/src/attributes/namespace.rs +++ b/crates/cgp-macro-lib/src/attributes/namespace.rs @@ -1,14 +1,11 @@ -use quote::quote; +use cgp_macro_core::types::path::UniPath; +use syn::Ident; use syn::parse::{Parse, ParseStream}; -use syn::punctuated::Punctuated; -use syn::token::{At, Colon, Dot}; -use syn::{Ident, Type, parse2}; - -use crate::parse::PathType; +use syn::token::Colon; pub struct UseNamespaceAttribute { pub namespace: Ident, - pub path: Type, + pub path: UniPath, } impl Parse for UseNamespaceAttribute { @@ -21,16 +18,7 @@ impl Parse for UseNamespaceAttribute { Ident::new("DefaultNamespace", input.span()) }; - let _: At = input.parse()?; - - let paths: Punctuated = Punctuated::parse_separated_nonempty(input)?; - - let raw_path_type = paths.into_iter().rev().fold( - quote!(PathNil), - |tail, PathType { path_type }| quote!(PathCons<#path_type, #tail>), - ); - - let path: Type = parse2(raw_path_type)?; + let path = input.parse()?; Ok(UseNamespaceAttribute { namespace, path }) } diff --git a/crates/cgp/src/lib.rs b/crates/cgp/src/lib.rs index f9d27a73..1874b49f 100644 --- a/crates/cgp/src/lib.rs +++ b/crates/cgp/src/lib.rs @@ -5,3 +5,5 @@ pub use {cgp_core as core, cgp_core::re_export_imports, cgp_extra as extra}; pub mod prelude; + +pub use prelude as macro_prelude; From f043a69d1cbc3588de8004d96c5dd820dcc4bdf2 Mon Sep 17 00:00:00 2001 From: Soares Chen Date: Sun, 17 May 2026 22:23:27 +0200 Subject: [PATCH 05/81] Add cgp-base and cgp-base-types crates --- Cargo.lock | 16 +++++++++++++++- Cargo.toml | 4 ++++ crates/cgp-base-types/Cargo.toml | 11 +++++++++++ crates/cgp-base-types/src/lib.rs | 5 +++++ crates/cgp-base-types/src/macro_prelude.rs | 1 + crates/cgp-base-types/src/traits/mod.rs | 3 +++ .../src/traits/static_format.rs | 0 .../src/types/chars.rs | 0 crates/cgp-base-types/src/types/mod.rs | 7 +++++++ .../src/types/product.rs | 0 .../src/types/symbol.rs | 0 crates/cgp-base/Cargo.toml | 14 ++++++++++++++ crates/cgp-base/src/lib.rs | 1 + crates/cgp-base/src/macro_prelude.rs | 2 ++ crates/cgp-component/src/lib.rs | 2 ++ crates/cgp-component/src/macro_prelude.rs | 6 ++++++ crates/cgp-error/Cargo.toml | 2 +- crates/cgp-error/src/traits/can_raise_error.rs | 3 +-- crates/cgp-error/src/traits/can_wrap_error.rs | 3 +-- crates/cgp-error/src/traits/has_error_type.rs | 6 +----- crates/cgp-field/Cargo.toml | 1 + crates/cgp-field/src/traits/mod.rs | 2 -- crates/cgp-field/src/types/mod.rs | 7 +------ crates/cgp-macro-core/src/macros.rs | 2 +- .../src/types/path/path_element.rs | 3 ++- 25 files changed, 80 insertions(+), 21 deletions(-) create mode 100644 crates/cgp-base-types/Cargo.toml create mode 100644 crates/cgp-base-types/src/lib.rs create mode 100644 crates/cgp-base-types/src/macro_prelude.rs create mode 100644 crates/cgp-base-types/src/traits/mod.rs rename crates/{cgp-field => cgp-base-types}/src/traits/static_format.rs (100%) rename crates/{cgp-field => cgp-base-types}/src/types/chars.rs (100%) create mode 100644 crates/cgp-base-types/src/types/mod.rs rename crates/{cgp-field => cgp-base-types}/src/types/product.rs (100%) rename crates/{cgp-field => cgp-base-types}/src/types/symbol.rs (100%) create mode 100644 crates/cgp-base/Cargo.toml create mode 100644 crates/cgp-base/src/lib.rs create mode 100644 crates/cgp-base/src/macro_prelude.rs create mode 100644 crates/cgp-component/src/macro_prelude.rs diff --git a/Cargo.lock b/Cargo.lock index e69dc313..282654c8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -25,6 +25,19 @@ dependencies = [ "syn", ] +[[package]] +name = "cgp-base" +version = "0.7.0" +dependencies = [ + "cgp-base-types", + "cgp-component", + "cgp-macro", +] + +[[package]] +name = "cgp-base-types" +version = "0.7.0" + [[package]] name = "cgp-component" version = "0.7.0" @@ -54,7 +67,7 @@ dependencies = [ name = "cgp-error" version = "0.7.0" dependencies = [ - "cgp-component", + "cgp-base", "cgp-field", "cgp-macro", "cgp-type", @@ -127,6 +140,7 @@ dependencies = [ name = "cgp-field" version = "0.7.0" dependencies = [ + "cgp-base-types", "cgp-component", "cgp-type", ] diff --git a/Cargo.toml b/Cargo.toml index 043c269e..4bfd4674 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,6 +4,8 @@ resolver = "3" members = [ "crates/cgp", + "crates/cgp-base", + "crates/cgp-base-types", "crates/cgp-core", "crates/cgp-extra", "crates/cgp-async-macro", @@ -39,6 +41,8 @@ keywords = ["cgp"] [workspace.dependencies] cgp = { version = "0.7.0", path = "./crates/cgp" } +cgp-base = { version = "0.7.0", path = "./crates/cgp-base" } +cgp-base-types = { version = "0.7.0", path = "./crates/cgp-base-types" } cgp-core = { version = "0.7.0", path = "./crates/cgp-core" } cgp-extra = { version = "0.7.0", path = "./crates/cgp-extra" } cgp-async-macro = { version = "0.7.0", path = "./crates/cgp-async-macro" } diff --git a/crates/cgp-base-types/Cargo.toml b/crates/cgp-base-types/Cargo.toml new file mode 100644 index 00000000..1db41cea --- /dev/null +++ b/crates/cgp-base-types/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "cgp-base-types" +version = "0.7.0" +edition = { workspace = true } +license = { workspace = true } +repository = { workspace = true } +authors = { workspace = true } +rust-version = { workspace = true } +keywords = { workspace = true } + +[dependencies] diff --git a/crates/cgp-base-types/src/lib.rs b/crates/cgp-base-types/src/lib.rs new file mode 100644 index 00000000..b59e7464 --- /dev/null +++ b/crates/cgp-base-types/src/lib.rs @@ -0,0 +1,5 @@ +#![allow(non_camel_case_types)] + +pub mod macro_prelude; +pub mod traits; +pub mod types; diff --git a/crates/cgp-base-types/src/macro_prelude.rs b/crates/cgp-base-types/src/macro_prelude.rs new file mode 100644 index 00000000..1b6a6584 --- /dev/null +++ b/crates/cgp-base-types/src/macro_prelude.rs @@ -0,0 +1 @@ +pub use crate::types::*; diff --git a/crates/cgp-base-types/src/traits/mod.rs b/crates/cgp-base-types/src/traits/mod.rs new file mode 100644 index 00000000..138bc454 --- /dev/null +++ b/crates/cgp-base-types/src/traits/mod.rs @@ -0,0 +1,3 @@ +mod static_format; + +pub use static_format::*; diff --git a/crates/cgp-field/src/traits/static_format.rs b/crates/cgp-base-types/src/traits/static_format.rs similarity index 100% rename from crates/cgp-field/src/traits/static_format.rs rename to crates/cgp-base-types/src/traits/static_format.rs diff --git a/crates/cgp-field/src/types/chars.rs b/crates/cgp-base-types/src/types/chars.rs similarity index 100% rename from crates/cgp-field/src/types/chars.rs rename to crates/cgp-base-types/src/types/chars.rs diff --git a/crates/cgp-base-types/src/types/mod.rs b/crates/cgp-base-types/src/types/mod.rs new file mode 100644 index 00000000..ff2d2b5a --- /dev/null +++ b/crates/cgp-base-types/src/types/mod.rs @@ -0,0 +1,7 @@ +mod chars; +mod product; +mod symbol; + +pub use chars::*; +pub use product::*; +pub use symbol::*; diff --git a/crates/cgp-field/src/types/product.rs b/crates/cgp-base-types/src/types/product.rs similarity index 100% rename from crates/cgp-field/src/types/product.rs rename to crates/cgp-base-types/src/types/product.rs diff --git a/crates/cgp-field/src/types/symbol.rs b/crates/cgp-base-types/src/types/symbol.rs similarity index 100% rename from crates/cgp-field/src/types/symbol.rs rename to crates/cgp-base-types/src/types/symbol.rs diff --git a/crates/cgp-base/Cargo.toml b/crates/cgp-base/Cargo.toml new file mode 100644 index 00000000..00548ed4 --- /dev/null +++ b/crates/cgp-base/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "cgp-base" +version = "0.7.0" +edition = { workspace = true } +license = { workspace = true } +repository = { workspace = true } +authors = { workspace = true } +rust-version = { workspace = true } +keywords = { workspace = true } + +[dependencies] +cgp-base-types = { workspace = true } +cgp-component = { workspace = true } +cgp-macro = { workspace = true } diff --git a/crates/cgp-base/src/lib.rs b/crates/cgp-base/src/lib.rs new file mode 100644 index 00000000..52669be9 --- /dev/null +++ b/crates/cgp-base/src/lib.rs @@ -0,0 +1 @@ +pub mod macro_prelude; diff --git a/crates/cgp-base/src/macro_prelude.rs b/crates/cgp-base/src/macro_prelude.rs new file mode 100644 index 00000000..6f11db29 --- /dev/null +++ b/crates/cgp-base/src/macro_prelude.rs @@ -0,0 +1,2 @@ +pub use cgp_base_types::macro_prelude::*; +pub use cgp_component::macro_prelude::*; diff --git a/crates/cgp-component/src/lib.rs b/crates/cgp-component/src/lib.rs index a92a79a1..836e8152 100644 --- a/crates/cgp-component/src/lib.rs +++ b/crates/cgp-component/src/lib.rs @@ -5,6 +5,8 @@ CGP component implementation. */ +pub mod macro_prelude; + mod namespaces; mod traits; mod types; diff --git a/crates/cgp-component/src/macro_prelude.rs b/crates/cgp-component/src/macro_prelude.rs new file mode 100644 index 00000000..35603179 --- /dev/null +++ b/crates/cgp-component/src/macro_prelude.rs @@ -0,0 +1,6 @@ +pub use crate::namespaces::DefaultNamespace; +pub use crate::traits::{CanUseComponent, DelegateComponent, IsProviderFor}; +pub use crate::types::{ + ConcatPath, PathCons, PathNil, RedirectLookup, UseContext, UseDefault, UseDelegate, UseFields, + WithContext, WithProvider, +}; diff --git a/crates/cgp-error/Cargo.toml b/crates/cgp-error/Cargo.toml index 061de754..d1f29476 100644 --- a/crates/cgp-error/Cargo.toml +++ b/crates/cgp-error/Cargo.toml @@ -12,7 +12,7 @@ description = """ """ [dependencies] -cgp-component = { workspace = true } +cgp = { version = "0.7.0", path = "../cgp-base", package = "cgp-base" } cgp-macro = { workspace = true } cgp-type = { workspace = true } cgp-field = { workspace = true } diff --git a/crates/cgp-error/src/traits/can_raise_error.rs b/crates/cgp-error/src/traits/can_raise_error.rs index 2865b095..866757a6 100644 --- a/crates/cgp-error/src/traits/can_raise_error.rs +++ b/crates/cgp-error/src/traits/can_raise_error.rs @@ -1,5 +1,4 @@ -use cgp_component::*; -use cgp_field::types::*; +use cgp::macro_prelude::*; use cgp_macro::cgp_component; use crate::traits::has_error_type::HasErrorType; diff --git a/crates/cgp-error/src/traits/can_wrap_error.rs b/crates/cgp-error/src/traits/can_wrap_error.rs index 1237f354..954b470b 100644 --- a/crates/cgp-error/src/traits/can_wrap_error.rs +++ b/crates/cgp-error/src/traits/can_wrap_error.rs @@ -1,5 +1,4 @@ -use cgp_component::*; -use cgp_field::types::*; +use cgp::macro_prelude::*; use cgp_macro::cgp_component; use crate::traits::HasErrorType; diff --git a/crates/cgp-error/src/traits/has_error_type.rs b/crates/cgp-error/src/traits/has_error_type.rs index 8c54d424..6cf37ee5 100644 --- a/crates/cgp-error/src/traits/has_error_type.rs +++ b/crates/cgp-error/src/traits/has_error_type.rs @@ -1,10 +1,6 @@ use core::fmt::Debug; -use cgp_component::{ - DefaultNamespace, DelegateComponent, IsProviderFor, PathCons, PathNil, RedirectLookup, - UseContext, WithProvider, -}; -use cgp_field::types::*; +use cgp::macro_prelude::*; use cgp_macro::cgp_type; use cgp_type::{TypeProvider, UseType}; diff --git a/crates/cgp-field/Cargo.toml b/crates/cgp-field/Cargo.toml index fd1d255f..7a32d855 100644 --- a/crates/cgp-field/Cargo.toml +++ b/crates/cgp-field/Cargo.toml @@ -12,5 +12,6 @@ description = """ """ [dependencies] +cgp-base-types = { workspace = true } cgp-component = { workspace = true } cgp-type = { workspace = true } diff --git a/crates/cgp-field/src/traits/mod.rs b/crates/cgp-field/src/traits/mod.rs index 63d13dc7..6ab96625 100644 --- a/crates/cgp-field/src/traits/mod.rs +++ b/crates/cgp-field/src/traits/mod.rs @@ -13,7 +13,6 @@ mod map_fields; mod map_type; mod map_type_ref; mod partial_data; -mod static_format; mod static_string; mod take_field; mod to_fields; @@ -35,7 +34,6 @@ pub use map_fields::*; pub use map_type::*; pub use map_type_ref::*; pub use partial_data::*; -pub use static_format::*; pub use static_string::*; pub use take_field::*; pub use to_fields::*; diff --git a/crates/cgp-field/src/types/mod.rs b/crates/cgp-field/src/types/mod.rs index be1dfcbc..02880ce3 100644 --- a/crates/cgp-field/src/types/mod.rs +++ b/crates/cgp-field/src/types/mod.rs @@ -1,17 +1,12 @@ -mod chars; mod field; mod index; mod life; mod mref; -mod product; mod sum; -mod symbol; -pub use chars::*; +pub use cgp_base_types::types::*; pub use field::*; pub use index::*; pub use life::*; pub use mref::*; -pub use product::*; pub use sum::*; -pub use symbol::*; diff --git a/crates/cgp-macro-core/src/macros.rs b/crates/cgp-macro-core/src/macros.rs index fb77383f..02db7ff4 100644 --- a/crates/cgp-macro-core/src/macros.rs +++ b/crates/cgp-macro-core/src/macros.rs @@ -5,7 +5,7 @@ macro_rules! export_construct { impl ::quote::ToTokens for $from { fn to_tokens(&self, tokens: &mut ::proc_macro2::TokenStream) { - tokens.extend(::quote::quote! { $to }) + tokens.extend(::quote::quote! { ::cgp::macro_prelude::$to }) } } }; diff --git a/crates/cgp-macro-core/src/types/path/path_element.rs b/crates/cgp-macro-core/src/types/path/path_element.rs index a8ff04e9..cc35f059 100644 --- a/crates/cgp-macro-core/src/types/path/path_element.rs +++ b/crates/cgp-macro-core/src/types/path/path_element.rs @@ -17,6 +17,7 @@ impl Parse for PathElement { let parsed = if let Ok(path_ident) = parse2::(ty.to_token_stream()) { let path_str = path_ident.to_string(); + if let Some(path_char) = path_str.chars().next() && path_char.is_ascii_lowercase() && !is_primitive_type(&path_str) @@ -51,7 +52,7 @@ impl ToTokens for PathElement { } } -pub fn is_primitive_type(ident: &str) -> bool { +fn is_primitive_type(ident: &str) -> bool { if (ident.starts_with("i") || ident.starts_with("u") || ident.starts_with("f")) && ident[1..].chars().all(|c| c.is_numeric()) { From bf1057972c4c51f0cb9591e8d784659988f39291 Mon Sep 17 00:00:00 2001 From: Soares Chen Date: Sun, 17 May 2026 22:28:00 +0200 Subject: [PATCH 06/81] Move path types --- Cargo.lock | 2 ++ crates/cgp-base-types/src/macro_prelude.rs | 1 + .../path.rs => cgp-base-types/src/traits/concat_path.rs} | 6 +----- crates/cgp-base-types/src/traits/mod.rs | 2 ++ crates/cgp-base-types/src/types/mod.rs | 2 ++ crates/cgp-base-types/src/types/path.rs | 5 +++++ crates/cgp-component/src/lib.rs | 3 +-- crates/cgp-component/src/macro_prelude.rs | 3 +-- crates/cgp-component/src/types/mod.rs | 2 -- crates/cgp-core/Cargo.toml | 1 + crates/cgp-core/src/prelude.rs | 5 +++-- crates/cgp-type/Cargo.toml | 1 + crates/cgp-type/src/traits/has_type.rs | 2 +- 13 files changed, 21 insertions(+), 14 deletions(-) rename crates/{cgp-component/src/types/path.rs => cgp-base-types/src/traits/concat_path.rs} (70%) create mode 100644 crates/cgp-base-types/src/types/path.rs diff --git a/Cargo.lock b/Cargo.lock index 282654c8..42982093 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -47,6 +47,7 @@ name = "cgp-core" version = "0.7.0" dependencies = [ "cgp-async-macro", + "cgp-base", "cgp-component", "cgp-error", "cgp-field", @@ -223,6 +224,7 @@ dependencies = [ name = "cgp-type" version = "0.7.0" dependencies = [ + "cgp-base", "cgp-component", "cgp-macro", ] diff --git a/crates/cgp-base-types/src/macro_prelude.rs b/crates/cgp-base-types/src/macro_prelude.rs index 1b6a6584..833e6e30 100644 --- a/crates/cgp-base-types/src/macro_prelude.rs +++ b/crates/cgp-base-types/src/macro_prelude.rs @@ -1 +1,2 @@ +pub use crate::traits::ConcatPath; pub use crate::types::*; diff --git a/crates/cgp-component/src/types/path.rs b/crates/cgp-base-types/src/traits/concat_path.rs similarity index 70% rename from crates/cgp-component/src/types/path.rs rename to crates/cgp-base-types/src/traits/concat_path.rs index c09902af..3aeef7fa 100644 --- a/crates/cgp-component/src/types/path.rs +++ b/crates/cgp-base-types/src/traits/concat_path.rs @@ -1,8 +1,4 @@ -use core::marker::PhantomData; - -pub struct PathCons(pub PhantomData, pub PhantomData); - -pub struct PathNil; +use crate::types::{PathCons, PathNil}; pub trait ConcatPath { type Output: ?Sized; diff --git a/crates/cgp-base-types/src/traits/mod.rs b/crates/cgp-base-types/src/traits/mod.rs index 138bc454..c1632d17 100644 --- a/crates/cgp-base-types/src/traits/mod.rs +++ b/crates/cgp-base-types/src/traits/mod.rs @@ -1,3 +1,5 @@ +mod concat_path; mod static_format; +pub use concat_path::*; pub use static_format::*; diff --git a/crates/cgp-base-types/src/types/mod.rs b/crates/cgp-base-types/src/types/mod.rs index ff2d2b5a..3b99d699 100644 --- a/crates/cgp-base-types/src/types/mod.rs +++ b/crates/cgp-base-types/src/types/mod.rs @@ -1,7 +1,9 @@ mod chars; +mod path; mod product; mod symbol; pub use chars::*; +pub use path::*; pub use product::*; pub use symbol::*; diff --git a/crates/cgp-base-types/src/types/path.rs b/crates/cgp-base-types/src/types/path.rs new file mode 100644 index 00000000..ca9ffba0 --- /dev/null +++ b/crates/cgp-base-types/src/types/path.rs @@ -0,0 +1,5 @@ +use core::marker::PhantomData; + +pub struct PathCons(pub PhantomData, pub PhantomData); + +pub struct PathNil; diff --git a/crates/cgp-component/src/lib.rs b/crates/cgp-component/src/lib.rs index 836e8152..65850055 100644 --- a/crates/cgp-component/src/lib.rs +++ b/crates/cgp-component/src/lib.rs @@ -14,6 +14,5 @@ mod types; pub use namespaces::DefaultNamespace; pub use traits::{CanUseComponent, DelegateComponent, IsProviderFor}; pub use types::{ - ConcatPath, PathCons, PathNil, RedirectLookup, UseContext, UseDefault, UseDelegate, UseFields, - WithContext, WithProvider, + RedirectLookup, UseContext, UseDefault, UseDelegate, UseFields, WithContext, WithProvider, }; diff --git a/crates/cgp-component/src/macro_prelude.rs b/crates/cgp-component/src/macro_prelude.rs index 35603179..26276db3 100644 --- a/crates/cgp-component/src/macro_prelude.rs +++ b/crates/cgp-component/src/macro_prelude.rs @@ -1,6 +1,5 @@ pub use crate::namespaces::DefaultNamespace; pub use crate::traits::{CanUseComponent, DelegateComponent, IsProviderFor}; pub use crate::types::{ - ConcatPath, PathCons, PathNil, RedirectLookup, UseContext, UseDefault, UseDelegate, UseFields, - WithContext, WithProvider, + RedirectLookup, UseContext, UseDefault, UseDelegate, UseFields, WithContext, WithProvider, }; diff --git a/crates/cgp-component/src/types/mod.rs b/crates/cgp-component/src/types/mod.rs index 56890656..1e07f782 100644 --- a/crates/cgp-component/src/types/mod.rs +++ b/crates/cgp-component/src/types/mod.rs @@ -1,4 +1,3 @@ -mod path; mod redirect_lookup; mod use_context; mod use_default; @@ -6,7 +5,6 @@ mod use_delegate; mod use_fields; mod with_provider; -pub use path::{ConcatPath, PathCons, PathNil}; pub use redirect_lookup::RedirectLookup; pub use use_context::{UseContext, WithContext}; pub use use_default::UseDefault; diff --git a/crates/cgp-core/Cargo.toml b/crates/cgp-core/Cargo.toml index 7aae1dc7..968e00a2 100644 --- a/crates/cgp-core/Cargo.toml +++ b/crates/cgp-core/Cargo.toml @@ -12,6 +12,7 @@ description = """ """ [dependencies] +cgp-base = { workspace = true } cgp-async-macro = { workspace = true } cgp-component = { workspace = true } cgp-macro = { workspace = true } diff --git a/crates/cgp-core/src/prelude.rs b/crates/cgp-core/src/prelude.rs index 41063b28..9c0254f1 100644 --- a/crates/cgp-core/src/prelude.rs +++ b/crates/cgp-core/src/prelude.rs @@ -1,9 +1,10 @@ pub use core::marker::PhantomData; pub use cgp_async_macro::async_trait; +pub use cgp_base::macro_prelude::{ConcatPath, PathCons, PathNil}; pub use cgp_component::{ - CanUseComponent, ConcatPath, DefaultNamespace, DelegateComponent, IsProviderFor, PathCons, - PathNil, RedirectLookup, UseContext, UseDelegate, UseFields, WithContext, WithProvider, + CanUseComponent, DefaultNamespace, DelegateComponent, IsProviderFor, RedirectLookup, + UseContext, UseDelegate, UseFields, WithContext, WithProvider, }; pub use cgp_error::{CanRaiseError, CanWrapError, HasErrorType}; pub use cgp_field::impls::{IsMut, IsNothing, IsPresent, IsRef, IsVoid, UseField}; diff --git a/crates/cgp-type/Cargo.toml b/crates/cgp-type/Cargo.toml index f9232b60..822af9ff 100644 --- a/crates/cgp-type/Cargo.toml +++ b/crates/cgp-type/Cargo.toml @@ -14,3 +14,4 @@ description = """ [dependencies] cgp-component = { workspace = true } cgp-macro = { workspace = true } +cgp-base = { workspace = true } diff --git a/crates/cgp-type/src/traits/has_type.rs b/crates/cgp-type/src/traits/has_type.rs index 84a39a3b..67f846a6 100644 --- a/crates/cgp-type/src/traits/has_type.rs +++ b/crates/cgp-type/src/traits/has_type.rs @@ -1,4 +1,4 @@ -use cgp_component::*; +use cgp_base::macro_prelude::*; use cgp_macro::cgp_component; #[cgp_component { From 1ee8022e5f29f65f24fdbcd2dc47a7012798e75b Mon Sep 17 00:00:00 2001 From: Soares Chen Date: Sun, 17 May 2026 22:30:46 +0200 Subject: [PATCH 07/81] Remove PathNil --- crates/cgp-base-types/src/traits/concat_path.rs | 4 ++-- .../src/types/{product.rs => cons.rs} | 14 -------------- crates/cgp-base-types/src/types/mod.rs | 6 ++++-- crates/cgp-base-types/src/types/nil.rs | 14 ++++++++++++++ crates/cgp-base-types/src/types/path.rs | 2 -- crates/cgp-core/src/prelude.rs | 2 +- crates/cgp-macro-core/src/exports.rs | 1 - crates/cgp-macro-core/src/types/path/unipath.rs | 4 ++-- crates/cgp-macro-lib/src/cgp_namespace/spec.rs | 2 +- .../src/derive_component/derive_redirect_lookup.rs | 2 +- .../cgp-macro-lib/src/parse/delegate_components.rs | 2 +- 11 files changed, 26 insertions(+), 27 deletions(-) rename crates/cgp-base-types/src/types/{product.rs => cons.rs} (70%) create mode 100644 crates/cgp-base-types/src/types/nil.rs diff --git a/crates/cgp-base-types/src/traits/concat_path.rs b/crates/cgp-base-types/src/traits/concat_path.rs index 3aeef7fa..f34f03b1 100644 --- a/crates/cgp-base-types/src/traits/concat_path.rs +++ b/crates/cgp-base-types/src/traits/concat_path.rs @@ -1,4 +1,4 @@ -use crate::types::{PathCons, PathNil}; +use crate::types::{Nil, PathCons}; pub trait ConcatPath { type Output: ?Sized; @@ -11,6 +11,6 @@ where type Output = PathCons>::Output>; } -impl ConcatPath for PathNil { +impl ConcatPath for Nil { type Output = Other; } diff --git a/crates/cgp-base-types/src/types/product.rs b/crates/cgp-base-types/src/types/cons.rs similarity index 70% rename from crates/cgp-base-types/src/types/product.rs rename to crates/cgp-base-types/src/types/cons.rs index 218aaec2..315c3f39 100644 --- a/crates/cgp-base-types/src/types/product.rs +++ b/crates/cgp-base-types/src/types/cons.rs @@ -34,18 +34,4 @@ #[allow(non_camel_case_types)] pub struct π(pub Head, pub Tail); -/** - The `Nil` type, a.k.a. `ε`, is used to represent the end of a _type-level list_, - or an empty type-level list. - - `Nil` is commonly used as the `Tail` of a [`Cons`] type, to terminate the list. - When used on its own, it represents an empty type-level list. - - Read more about type-level lists, a.k.a. the product types, in [`Cons`]. -*/ -#[derive(Eq, PartialEq, Clone, Default, Debug)] -#[allow(non_camel_case_types)] -pub struct ε; - -pub use ε as Nil; pub use π as Cons; diff --git a/crates/cgp-base-types/src/types/mod.rs b/crates/cgp-base-types/src/types/mod.rs index 3b99d699..ccc13be7 100644 --- a/crates/cgp-base-types/src/types/mod.rs +++ b/crates/cgp-base-types/src/types/mod.rs @@ -1,9 +1,11 @@ mod chars; +mod cons; +mod nil; mod path; -mod product; mod symbol; pub use chars::*; +pub use cons::*; +pub use nil::*; pub use path::*; -pub use product::*; pub use symbol::*; diff --git a/crates/cgp-base-types/src/types/nil.rs b/crates/cgp-base-types/src/types/nil.rs new file mode 100644 index 00000000..9f6ee60d --- /dev/null +++ b/crates/cgp-base-types/src/types/nil.rs @@ -0,0 +1,14 @@ +/** + The `Nil` type, a.k.a. `ε`, is used to represent the end of a _type-level list_, + or an empty type-level list. + + `Nil` is commonly used as the `Tail` of a [`Cons`] type, to terminate the list. + When used on its own, it represents an empty type-level list. + + Read more about type-level lists, a.k.a. the product types, in [`Cons`]. +*/ +#[derive(Eq, PartialEq, Clone, Default, Debug)] +#[allow(non_camel_case_types)] +pub struct ε; + +pub use ε as Nil; diff --git a/crates/cgp-base-types/src/types/path.rs b/crates/cgp-base-types/src/types/path.rs index ca9ffba0..48bc11bf 100644 --- a/crates/cgp-base-types/src/types/path.rs +++ b/crates/cgp-base-types/src/types/path.rs @@ -1,5 +1,3 @@ use core::marker::PhantomData; pub struct PathCons(pub PhantomData, pub PhantomData); - -pub struct PathNil; diff --git a/crates/cgp-core/src/prelude.rs b/crates/cgp-core/src/prelude.rs index 9c0254f1..5702afab 100644 --- a/crates/cgp-core/src/prelude.rs +++ b/crates/cgp-core/src/prelude.rs @@ -1,7 +1,7 @@ pub use core::marker::PhantomData; pub use cgp_async_macro::async_trait; -pub use cgp_base::macro_prelude::{ConcatPath, PathCons, PathNil}; +pub use cgp_base::macro_prelude::{ConcatPath, PathCons}; pub use cgp_component::{ CanUseComponent, DefaultNamespace, DelegateComponent, IsProviderFor, RedirectLookup, UseContext, UseDelegate, UseFields, WithContext, WithProvider, diff --git a/crates/cgp-macro-core/src/exports.rs b/crates/cgp-macro-core/src/exports.rs index 0bbec9d6..7951ad81 100644 --- a/crates/cgp-macro-core/src/exports.rs +++ b/crates/cgp-macro-core/src/exports.rs @@ -6,5 +6,4 @@ export_constructs! { Chars => ζ, Symbol => ψ, PathCons, - PathNil, } diff --git a/crates/cgp-macro-core/src/types/path/unipath.rs b/crates/cgp-macro-core/src/types/path/unipath.rs index d4afbbda..46d3411f 100644 --- a/crates/cgp-macro-core/src/types/path/unipath.rs +++ b/crates/cgp-macro-core/src/types/path/unipath.rs @@ -5,7 +5,7 @@ use syn::parse::{Parse, ParseStream}; use syn::punctuated::Punctuated; use syn::token::{At, Dot}; -use crate::exports::{PathCons, PathNil}; +use crate::exports::{Nil, PathCons}; use crate::types::path::PathElement; pub struct UniPath { @@ -31,7 +31,7 @@ impl Parse for UniPath { impl ToTokens for UniPath { fn to_tokens(&self, tokens: &mut TokenStream) { let out = self.elements.iter().rev().fold( - quote!(#PathNil), + quote!(#Nil), |acc, current| quote!( #PathCons < #current, #acc > ), ); diff --git a/crates/cgp-macro-lib/src/cgp_namespace/spec.rs b/crates/cgp-macro-lib/src/cgp_namespace/spec.rs index 837b7766..21e19a73 100644 --- a/crates/cgp-macro-lib/src/cgp_namespace/spec.rs +++ b/crates/cgp-macro-lib/src/cgp_namespace/spec.rs @@ -72,7 +72,7 @@ impl Parse for NamespaceEntry { let value_path: Punctuated = Punctuated::parse_separated_nonempty(input)?; let value = value_path.into_iter().rev().fold( - quote!(PathNil), + quote!(Nil), |tail, PathType { path_type }| quote!( PathCons< #path_type, #tail > ), ); diff --git a/crates/cgp-macro-lib/src/derive_component/derive_redirect_lookup.rs b/crates/cgp-macro-lib/src/derive_component/derive_redirect_lookup.rs index ea294f3f..6c3be886 100644 --- a/crates/cgp-macro-lib/src/derive_component/derive_redirect_lookup.rs +++ b/crates/cgp-macro-lib/src/derive_component/derive_redirect_lookup.rs @@ -86,7 +86,7 @@ pub fn extract_type_generics(generics: &Generics) -> syn::Result> { if type_params.is_empty() { Ok(None) } else { - let mut out = quote! { PathNil }; + let mut out = quote! { Nil }; for param in type_params.iter().rev() { out = quote! { diff --git a/crates/cgp-macro-lib/src/parse/delegate_components.rs b/crates/cgp-macro-lib/src/parse/delegate_components.rs index 28cfcae3..19fa475f 100644 --- a/crates/cgp-macro-lib/src/parse/delegate_components.rs +++ b/crates/cgp-macro-lib/src/parse/delegate_components.rs @@ -130,7 +130,7 @@ pub fn parse_meta_delegate_entries( for component in components { let value = DelegateValue::Type(parse2( - quote!(RedirectLookup<#target_type, PathCons<#component, PathNil>>), + quote!(RedirectLookup<#target_type, PathCons<#component, ε>>), )?); let key = DelegateKey { From eccb29f1bcf42f63c0c17ddfc452f3a2846c3e4b Mon Sep 17 00:00:00 2001 From: Soares Chen Date: Sun, 17 May 2026 22:31:44 +0200 Subject: [PATCH 08/81] Rename cgp_component::types to providers --- crates/cgp-component/src/lib.rs | 6 +++--- crates/cgp-component/src/macro_prelude.rs | 4 ++-- crates/cgp-component/src/{types => providers}/mod.rs | 0 .../src/{types => providers}/redirect_lookup.rs | 0 .../cgp-component/src/{types => providers}/use_context.rs | 0 .../cgp-component/src/{types => providers}/use_default.rs | 0 .../cgp-component/src/{types => providers}/use_delegate.rs | 0 crates/cgp-component/src/{types => providers}/use_field.rs | 0 crates/cgp-component/src/{types => providers}/use_fields.rs | 0 .../cgp-component/src/{types => providers}/with_provider.rs | 0 10 files changed, 5 insertions(+), 5 deletions(-) rename crates/cgp-component/src/{types => providers}/mod.rs (100%) rename crates/cgp-component/src/{types => providers}/redirect_lookup.rs (100%) rename crates/cgp-component/src/{types => providers}/use_context.rs (100%) rename crates/cgp-component/src/{types => providers}/use_default.rs (100%) rename crates/cgp-component/src/{types => providers}/use_delegate.rs (100%) rename crates/cgp-component/src/{types => providers}/use_field.rs (100%) rename crates/cgp-component/src/{types => providers}/use_fields.rs (100%) rename crates/cgp-component/src/{types => providers}/with_provider.rs (100%) diff --git a/crates/cgp-component/src/lib.rs b/crates/cgp-component/src/lib.rs index 65850055..cf9b41f5 100644 --- a/crates/cgp-component/src/lib.rs +++ b/crates/cgp-component/src/lib.rs @@ -8,11 +8,11 @@ pub mod macro_prelude; mod namespaces; +mod providers; mod traits; -mod types; pub use namespaces::DefaultNamespace; -pub use traits::{CanUseComponent, DelegateComponent, IsProviderFor}; -pub use types::{ +pub use providers::{ RedirectLookup, UseContext, UseDefault, UseDelegate, UseFields, WithContext, WithProvider, }; +pub use traits::{CanUseComponent, DelegateComponent, IsProviderFor}; diff --git a/crates/cgp-component/src/macro_prelude.rs b/crates/cgp-component/src/macro_prelude.rs index 26276db3..f08affab 100644 --- a/crates/cgp-component/src/macro_prelude.rs +++ b/crates/cgp-component/src/macro_prelude.rs @@ -1,5 +1,5 @@ pub use crate::namespaces::DefaultNamespace; -pub use crate::traits::{CanUseComponent, DelegateComponent, IsProviderFor}; -pub use crate::types::{ +pub use crate::providers::{ RedirectLookup, UseContext, UseDefault, UseDelegate, UseFields, WithContext, WithProvider, }; +pub use crate::traits::{CanUseComponent, DelegateComponent, IsProviderFor}; diff --git a/crates/cgp-component/src/types/mod.rs b/crates/cgp-component/src/providers/mod.rs similarity index 100% rename from crates/cgp-component/src/types/mod.rs rename to crates/cgp-component/src/providers/mod.rs diff --git a/crates/cgp-component/src/types/redirect_lookup.rs b/crates/cgp-component/src/providers/redirect_lookup.rs similarity index 100% rename from crates/cgp-component/src/types/redirect_lookup.rs rename to crates/cgp-component/src/providers/redirect_lookup.rs diff --git a/crates/cgp-component/src/types/use_context.rs b/crates/cgp-component/src/providers/use_context.rs similarity index 100% rename from crates/cgp-component/src/types/use_context.rs rename to crates/cgp-component/src/providers/use_context.rs diff --git a/crates/cgp-component/src/types/use_default.rs b/crates/cgp-component/src/providers/use_default.rs similarity index 100% rename from crates/cgp-component/src/types/use_default.rs rename to crates/cgp-component/src/providers/use_default.rs diff --git a/crates/cgp-component/src/types/use_delegate.rs b/crates/cgp-component/src/providers/use_delegate.rs similarity index 100% rename from crates/cgp-component/src/types/use_delegate.rs rename to crates/cgp-component/src/providers/use_delegate.rs diff --git a/crates/cgp-component/src/types/use_field.rs b/crates/cgp-component/src/providers/use_field.rs similarity index 100% rename from crates/cgp-component/src/types/use_field.rs rename to crates/cgp-component/src/providers/use_field.rs diff --git a/crates/cgp-component/src/types/use_fields.rs b/crates/cgp-component/src/providers/use_fields.rs similarity index 100% rename from crates/cgp-component/src/types/use_fields.rs rename to crates/cgp-component/src/providers/use_fields.rs diff --git a/crates/cgp-component/src/types/with_provider.rs b/crates/cgp-component/src/providers/with_provider.rs similarity index 100% rename from crates/cgp-component/src/types/with_provider.rs rename to crates/cgp-component/src/providers/with_provider.rs From 5bed597467dc2c3da1f49421f68a23ea447177de Mon Sep 17 00:00:00 2001 From: Soares Chen Date: Sun, 17 May 2026 22:55:59 +0200 Subject: [PATCH 09/81] Use UniPath in NamespaceEntry --- .../cgp-macro-core/src/types/path/unipath.rs | 2 +- .../cgp-macro-lib/src/cgp_namespace/spec.rs | 21 ++++++------------- 2 files changed, 7 insertions(+), 16 deletions(-) diff --git a/crates/cgp-macro-core/src/types/path/unipath.rs b/crates/cgp-macro-core/src/types/path/unipath.rs index 46d3411f..89b57bbe 100644 --- a/crates/cgp-macro-core/src/types/path/unipath.rs +++ b/crates/cgp-macro-core/src/types/path/unipath.rs @@ -22,7 +22,7 @@ impl Parse for UniPath { fn parse(input: ParseStream) -> syn::Result { let _: At = input.parse()?; - let elements = Punctuated::parse_terminated(input)?; + let elements = Punctuated::parse_separated_nonempty(input)?; Ok(Self { elements }) } diff --git a/crates/cgp-macro-lib/src/cgp_namespace/spec.rs b/crates/cgp-macro-lib/src/cgp_namespace/spec.rs index 21e19a73..e5847d8a 100644 --- a/crates/cgp-macro-lib/src/cgp_namespace/spec.rs +++ b/crates/cgp-macro-lib/src/cgp_namespace/spec.rs @@ -1,10 +1,10 @@ -use quote::quote; +use cgp_macro_core::types::path::UniPath; use syn::parse::{Parse, ParseStream}; use syn::punctuated::Punctuated; -use syn::token::{At, Colon, Comma, Dot, Lt}; -use syn::{Ident, Type, braced, parse2}; +use syn::token::{At, Colon, Comma, Lt}; +use syn::{Ident, Type, braced}; -use crate::parse::{ComponentPath, ComponentPaths, ImplGenerics, PathType}; +use crate::parse::{ComponentPath, ComponentPaths, ImplGenerics}; pub struct NamespaceSpec { pub namespace_ident: Ident, @@ -14,7 +14,7 @@ pub struct NamespaceSpec { pub struct NamespaceEntry { pub keys: ComponentPaths, - pub value: Type, + pub value: UniPath, } impl Parse for NamespaceSpec { @@ -67,16 +67,7 @@ impl Parse for NamespaceEntry { let _: Colon = input.parse()?; - let _: At = input.parse()?; - - let value_path: Punctuated = Punctuated::parse_separated_nonempty(input)?; - - let value = value_path.into_iter().rev().fold( - quote!(Nil), - |tail, PathType { path_type }| quote!( PathCons< #path_type, #tail > ), - ); - - let value: Type = parse2(value)?; + let value = input.parse()?; Ok(Self { keys, value }) } From f7d6e8802afb288133d0208b20ccc5f1d91c58fd Mon Sep 17 00:00:00 2001 From: Soares Chen Date: Sun, 17 May 2026 23:01:47 +0200 Subject: [PATCH 10/81] Split out derive_namespace --- .../cgp-macro-lib/src/cgp_namespace/derive.rs | 82 +++++++++++++++++++ crates/cgp-macro-lib/src/cgp_namespace/mod.rs | 6 +- .../src/entrypoints/cgp_namespace.rs | 78 +----------------- 3 files changed, 90 insertions(+), 76 deletions(-) create mode 100644 crates/cgp-macro-lib/src/cgp_namespace/derive.rs diff --git a/crates/cgp-macro-lib/src/cgp_namespace/derive.rs b/crates/cgp-macro-lib/src/cgp_namespace/derive.rs new file mode 100644 index 00000000..229af26b --- /dev/null +++ b/crates/cgp-macro-lib/src/cgp_namespace/derive.rs @@ -0,0 +1,82 @@ +use proc_macro2::TokenStream; +use quote::quote; +use syn::{Ident, ItemImpl, ItemStruct, ItemTrait, parse_quote, parse2}; + +use crate::cgp_namespace::NamespaceSpec; + +pub fn derive_namespace(spec: NamespaceSpec) -> syn::Result { + let mut out = TokenStream::new(); + + let namespace_ident = &spec.namespace_ident; + + let namespace_trait: ItemTrait = parse2(quote! { + pub trait #namespace_ident< __Components__ > { + type Provider; + } + })?; + + out.extend(quote! { + #namespace_trait + }); + + if let Some(parent_namespace_ident) = spec.parent_namespace_ident { + let namespace_struct_ident = Ident::new( + &format!("__{}Components", namespace_ident), + namespace_ident.span(), + ); + + let namespace_struct: ItemStruct = parse2(quote! { + pub struct #namespace_struct_ident; + })?; + + let item_impl: ItemImpl = parse2(quote! { + impl<__Context__, __Components__, __Provider__> + #namespace_ident< __Components__ > + for __Context__ + where + __Context__: #parent_namespace_ident< __Components__, Provider = __Provider__ > + + #parent_namespace_ident< #namespace_struct_ident >, + { + type Provider = __Provider__; + } + })?; + + out.extend(quote! { + #namespace_struct + + #item_impl + }) + } + + for entry in spec.entries.into_iter() { + let value = entry.value; + // value.append_type(parse_quote!(__Wildcard__)); + + for path in entry.keys.paths.into_iter() { + let path_type = path.path_type; + + let mut generics = path.generics.generics; + generics.params.push(parse_quote!(__Components__)); + + let impl_generics = generics.split_for_impl().0; + + let item_impl: ItemImpl = parse2(quote! { + impl #impl_generics + #namespace_ident< __Components__ > + for #path_type + { + type Provider = RedirectLookup< + __Components__, + #value, + >; + } + })?; + + out.extend(quote! { + #item_impl + }) + } + } + + Ok(out) +} diff --git a/crates/cgp-macro-lib/src/cgp_namespace/mod.rs b/crates/cgp-macro-lib/src/cgp_namespace/mod.rs index cc05df3b..50a77047 100644 --- a/crates/cgp-macro-lib/src/cgp_namespace/mod.rs +++ b/crates/cgp-macro-lib/src/cgp_namespace/mod.rs @@ -1 +1,5 @@ -pub mod spec; +mod derive; +mod spec; + +pub use derive::*; +pub use spec::*; diff --git a/crates/cgp-macro-lib/src/entrypoints/cgp_namespace.rs b/crates/cgp-macro-lib/src/entrypoints/cgp_namespace.rs index 7b39a741..0c2623be 100644 --- a/crates/cgp-macro-lib/src/entrypoints/cgp_namespace.rs +++ b/crates/cgp-macro-lib/src/entrypoints/cgp_namespace.rs @@ -1,82 +1,10 @@ use proc_macro2::TokenStream; -use quote::quote; -use syn::{Ident, ItemImpl, ItemStruct, ItemTrait, parse2}; +use syn::parse2; -use crate::cgp_namespace::spec::NamespaceSpec; +use crate::cgp_namespace::{NamespaceSpec, derive_namespace}; pub fn cgp_namespace(body: TokenStream) -> syn::Result { let spec: NamespaceSpec = parse2(body)?; - let mut out = TokenStream::new(); - - let namespace_ident = &spec.namespace_ident; - - let namespace_trait: ItemTrait = parse2(quote! { - pub trait #namespace_ident< __Components__ > { - type Provider; - } - })?; - - out.extend(quote! { - #namespace_trait - }); - - if let Some(parent_namespace_ident) = spec.parent_namespace_ident { - let namespace_struct_ident = Ident::new( - &format!("__{}Components", namespace_ident), - namespace_ident.span(), - ); - - let namespace_struct: ItemStruct = parse2(quote! { - pub struct #namespace_struct_ident; - })?; - - let item_impl: ItemImpl = parse2(quote! { - impl<__Context__, __Components__, __Provider__> - #namespace_ident< __Components__ > - for __Context__ - where - __Context__: #parent_namespace_ident< __Components__, Provider = __Provider__ > - + #parent_namespace_ident< #namespace_struct_ident >, - { - type Provider = __Provider__; - } - })?; - - out.extend(quote! { - #namespace_struct - - #item_impl - }) - } - - for entry in spec.entries.into_iter() { - let value = entry.value; - for path in entry.keys.paths.into_iter() { - let path_type = path.path_type; - - let mut generics = path.generics.generics; - generics.params.push(parse2(quote!(__Components__))?); - - let impl_generics = generics.split_for_impl().0; - - let item_impl: ItemImpl = parse2(quote! { - impl #impl_generics - #namespace_ident< __Components__ > - for #path_type - { - type Provider = RedirectLookup< - __Components__, - #value, - >; - } - })?; - - out.extend(quote! { - #item_impl - }) - } - } - - Ok(out) + derive_namespace(spec) } From 8a953f54576fef7d616d3e9bb36fd389a9d6bf0d Mon Sep 17 00:00:00 2001 From: Soares Chen Date: Sun, 17 May 2026 23:14:32 +0200 Subject: [PATCH 11/81] Move ImplGenerics --- .../src/types}/impl_generics.rs | 13 ++++++++----- crates/cgp-macro-core/src/types/mod.rs | 9 +++++++-- crates/cgp-macro-core/src/types/path/mod.rs | 2 ++ crates/cgp-macro-core/src/types/path/nested_path.rs | 1 + crates/cgp-macro-lib/src/attributes/namespace.rs | 2 +- crates/cgp-macro-lib/src/cgp_namespace/spec.rs | 4 ++-- .../src/delegate_components/impl_delegate.rs | 3 ++- crates/cgp-macro-lib/src/entrypoints/cgp_preset.rs | 5 +++-- .../entrypoints/delegate_and_check_components.rs | 2 +- crates/cgp-macro-lib/src/parse/check_components.rs | 3 ++- .../src/parse/delegate_and_check_components.rs | 3 ++- .../cgp-macro-lib/src/parse/delegate_components.rs | 3 ++- crates/cgp-macro-lib/src/parse/mod.rs | 2 -- crates/cgp-macro-lib/src/parse/path.rs | 2 +- crates/cgp-macro-lib/src/parse/type_spec.rs | 3 +-- crates/cgp-macro-lib/src/preset/impl_is_preset.rs | 3 ++- 16 files changed, 37 insertions(+), 23 deletions(-) rename crates/{cgp-macro-lib/src/parse => cgp-macro-core/src/types}/impl_generics.rs (77%) create mode 100644 crates/cgp-macro-core/src/types/path/nested_path.rs diff --git a/crates/cgp-macro-lib/src/parse/impl_generics.rs b/crates/cgp-macro-core/src/types/impl_generics.rs similarity index 77% rename from crates/cgp-macro-lib/src/parse/impl_generics.rs rename to crates/cgp-macro-core/src/types/impl_generics.rs index 7828aed8..71417e52 100644 --- a/crates/cgp-macro-lib/src/parse/impl_generics.rs +++ b/crates/cgp-macro-core/src/types/impl_generics.rs @@ -1,17 +1,20 @@ +use core::ops::Deref; + use proc_macro2::TokenStream; use quote::ToTokens; use syn::parse::{Parse, ParseStream}; -use syn::{Error, Generics, TypeGenerics, parse2}; +use syn::{Error, Generics, parse2}; #[derive(Clone, Default)] pub struct ImplGenerics { pub generics: Generics, } -impl ImplGenerics { - pub fn as_type_generics(&self) -> TypeGenerics<'_> { - let (_, type_generics, _) = self.generics.split_for_impl(); - type_generics +impl Deref for ImplGenerics { + type Target = Generics; + + fn deref(&self) -> &Generics { + &self.generics } } diff --git a/crates/cgp-macro-core/src/types/mod.rs b/crates/cgp-macro-core/src/types/mod.rs index c21b6234..147b054d 100644 --- a/crates/cgp-macro-core/src/types/mod.rs +++ b/crates/cgp-macro-core/src/types/mod.rs @@ -1,2 +1,7 @@ -pub mod path; -pub mod symbol; +mod impl_generics; +mod path; +mod symbol; + +pub use impl_generics::*; +pub use path::*; +pub use symbol::*; diff --git a/crates/cgp-macro-core/src/types/path/mod.rs b/crates/cgp-macro-core/src/types/path/mod.rs index 5ef6775f..5f913922 100644 --- a/crates/cgp-macro-core/src/types/path/mod.rs +++ b/crates/cgp-macro-core/src/types/path/mod.rs @@ -1,5 +1,7 @@ +mod nested_path; mod path_element; mod unipath; +pub use nested_path::*; pub use path_element::*; pub use unipath::*; diff --git a/crates/cgp-macro-core/src/types/path/nested_path.rs b/crates/cgp-macro-core/src/types/path/nested_path.rs new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/crates/cgp-macro-core/src/types/path/nested_path.rs @@ -0,0 +1 @@ + diff --git a/crates/cgp-macro-lib/src/attributes/namespace.rs b/crates/cgp-macro-lib/src/attributes/namespace.rs index b57f94d5..d16bf207 100644 --- a/crates/cgp-macro-lib/src/attributes/namespace.rs +++ b/crates/cgp-macro-lib/src/attributes/namespace.rs @@ -1,4 +1,4 @@ -use cgp_macro_core::types::path::UniPath; +use cgp_macro_core::types::UniPath; use syn::Ident; use syn::parse::{Parse, ParseStream}; use syn::token::Colon; diff --git a/crates/cgp-macro-lib/src/cgp_namespace/spec.rs b/crates/cgp-macro-lib/src/cgp_namespace/spec.rs index e5847d8a..89859be8 100644 --- a/crates/cgp-macro-lib/src/cgp_namespace/spec.rs +++ b/crates/cgp-macro-lib/src/cgp_namespace/spec.rs @@ -1,10 +1,10 @@ -use cgp_macro_core::types::path::UniPath; +use cgp_macro_core::types::{ImplGenerics, UniPath}; use syn::parse::{Parse, ParseStream}; use syn::punctuated::Punctuated; use syn::token::{At, Colon, Comma, Lt}; use syn::{Ident, Type, braced}; -use crate::parse::{ComponentPath, ComponentPaths, ImplGenerics}; +use crate::parse::{ComponentPath, ComponentPaths}; pub struct NamespaceSpec { pub namespace_ident: Ident, diff --git a/crates/cgp-macro-lib/src/delegate_components/impl_delegate.rs b/crates/cgp-macro-lib/src/delegate_components/impl_delegate.rs index 9722c269..312af732 100644 --- a/crates/cgp-macro-lib/src/delegate_components/impl_delegate.rs +++ b/crates/cgp-macro-lib/src/delegate_components/impl_delegate.rs @@ -2,6 +2,7 @@ use alloc::boxed::Box; use alloc::vec; use alloc::vec::Vec; +use cgp_macro_core::types::ImplGenerics; use proc_macro2::TokenStream; use quote::{ToTokens, quote}; use syn::punctuated::Punctuated; @@ -10,7 +11,7 @@ use syn::{ImplItem, ImplItemType, ItemImpl, Path, Type, parse2}; use crate::delegate_components::define_struct; use crate::delegate_components::merge_generics::merge_generics; -use crate::parse::{DelegateEntry, DelegateKey, DelegateMode, DelegateValue, ImplGenerics}; +use crate::parse::{DelegateEntry, DelegateKey, DelegateMode, DelegateValue}; pub fn impl_delegate_components( target_type: &Type, diff --git a/crates/cgp-macro-lib/src/entrypoints/cgp_preset.rs b/crates/cgp-macro-lib/src/entrypoints/cgp_preset.rs index 847dfd96..ba0d8ac6 100644 --- a/crates/cgp-macro-lib/src/entrypoints/cgp_preset.rs +++ b/crates/cgp-macro-lib/src/entrypoints/cgp_preset.rs @@ -1,5 +1,6 @@ use std::collections::HashSet; +use cgp_macro_core::types::ImplGenerics; use proc_macro2::{Span, TokenStream}; use quote::{ToTokens, TokenStreamExt, quote}; use syn::punctuated::Punctuated; @@ -7,7 +8,7 @@ use syn::token::{At, Comma}; use syn::{GenericParam, Ident, ItemTrait, TypeParamBound, parse_quote, parse2}; use crate::delegate_components::{define_struct, impl_delegate_components}; -use crate::parse::{DefinePreset, DelegateEntry, ImplGenerics, SimpleType}; +use crate::parse::{DefinePreset, DelegateEntry, SimpleType}; use crate::preset::{define_substitution_macro, impl_components_is_preset}; use crate::replace_self::to_snake_case_str; @@ -100,7 +101,7 @@ pub fn define_preset(body: TokenStream) -> syn::Result { let preset_generics: ImplGenerics = syn::parse2(quote!( #preset_generic_args ))?; let provider_type = { - let type_generics = preset_generics.as_type_generics(); + let type_generics = preset_generics.split_for_impl().1; parse2(quote! { #provider_struct_name #type_generics })? }; diff --git a/crates/cgp-macro-lib/src/entrypoints/delegate_and_check_components.rs b/crates/cgp-macro-lib/src/entrypoints/delegate_and_check_components.rs index 6f635434..986a17b3 100644 --- a/crates/cgp-macro-lib/src/entrypoints/delegate_and_check_components.rs +++ b/crates/cgp-macro-lib/src/entrypoints/delegate_and_check_components.rs @@ -1,3 +1,4 @@ +use cgp_macro_core::types::ImplGenerics; use proc_macro2::{Span, TokenStream}; use quote::{ToTokens, TokenStreamExt}; use syn::punctuated::Punctuated; @@ -9,7 +10,6 @@ use crate::check_components::derive_check_components; use crate::delegate_components::impl_delegate_components; use crate::parse::{ CheckComponents, CheckEntries, CheckEntry, DelegateAndCheckSpec, DelegateEntry, DelegateKey, - ImplGenerics, }; pub fn delegate_and_check_components(body: TokenStream) -> syn::Result { diff --git a/crates/cgp-macro-lib/src/parse/check_components.rs b/crates/cgp-macro-lib/src/parse/check_components.rs index cbfdee97..cc85bad0 100644 --- a/crates/cgp-macro-lib/src/parse/check_components.rs +++ b/crates/cgp-macro-lib/src/parse/check_components.rs @@ -1,3 +1,4 @@ +use cgp_macro_core::types::ImplGenerics; use proc_macro2::Span; use quote::ToTokens; use syn::parse::{Parse, ParseStream}; @@ -6,7 +7,7 @@ use syn::spanned::Spanned; use syn::token::{Bracket, Colon, Comma, Lt, Pound, Where}; use syn::{Attribute, Ident, Type, WhereClause, braced, bracketed, parse2}; -use crate::parse::{ImplGenerics, SimpleType}; +use crate::parse::SimpleType; pub struct CheckComponentsSpecs { pub specs: Vec, diff --git a/crates/cgp-macro-lib/src/parse/delegate_and_check_components.rs b/crates/cgp-macro-lib/src/parse/delegate_and_check_components.rs index 118d0f5e..2d07ef7f 100644 --- a/crates/cgp-macro-lib/src/parse/delegate_and_check_components.rs +++ b/crates/cgp-macro-lib/src/parse/delegate_and_check_components.rs @@ -1,5 +1,6 @@ use core::iter; +use cgp_macro_core::types::ImplGenerics; use quote::ToTokens; use syn::parse::{Parse, ParseStream}; use syn::punctuated::Punctuated; @@ -7,7 +8,7 @@ use syn::spanned::Spanned; use syn::token::{Bracket, Comma, Lt, Pound}; use syn::{Attribute, Ident, Type, braced, bracketed, parse2}; -use crate::parse::{DelegateMode, DelegateValue, ImplGenerics, SimpleType}; +use crate::parse::{DelegateMode, DelegateValue, SimpleType}; pub struct DelegateAndCheckSpec { pub impl_generics: ImplGenerics, diff --git a/crates/cgp-macro-lib/src/parse/delegate_components.rs b/crates/cgp-macro-lib/src/parse/delegate_components.rs index 19fa475f..4dc5d010 100644 --- a/crates/cgp-macro-lib/src/parse/delegate_components.rs +++ b/crates/cgp-macro-lib/src/parse/delegate_components.rs @@ -1,5 +1,6 @@ use core::iter; +use cgp_macro_core::types::ImplGenerics; use proc_macro2::{Span, TokenStream}; use quote::{ToTokens, TokenStreamExt, quote}; use syn::parse::discouraged::Speculative; @@ -9,7 +10,7 @@ use syn::token::{At, Bracket, Colon, Comma, Gt, Lt, RArrow, Semi}; use syn::{Error, Generics, Ident, Token, Type, braced, bracketed, parse_quote, parse2}; use crate::delegate_components::merge_generics; -use crate::parse::{ComponentPaths, ImplGenerics, SimpleType, TypeGenerics}; +use crate::parse::{ComponentPaths, SimpleType, TypeGenerics}; pub struct DelegateComponents { pub new_struct: bool, diff --git a/crates/cgp-macro-lib/src/parse/mod.rs b/crates/cgp-macro-lib/src/parse/mod.rs index 0c63770c..20ebbf99 100644 --- a/crates/cgp-macro-lib/src/parse/mod.rs +++ b/crates/cgp-macro-lib/src/parse/mod.rs @@ -4,7 +4,6 @@ mod define_preset; mod delegate_and_check_components; mod delegate_components; mod entry; -mod impl_generics; mod is_provider_params; mod path; mod simple_type; @@ -17,7 +16,6 @@ pub use define_preset::*; pub use delegate_and_check_components::*; pub use delegate_components::*; pub use entry::*; -pub use impl_generics::*; pub use is_provider_params::*; pub use path::*; pub use simple_type::*; diff --git a/crates/cgp-macro-lib/src/parse/path.rs b/crates/cgp-macro-lib/src/parse/path.rs index 78d91694..fe6c2d18 100644 --- a/crates/cgp-macro-lib/src/parse/path.rs +++ b/crates/cgp-macro-lib/src/parse/path.rs @@ -1,3 +1,4 @@ +use cgp_macro_core::types::ImplGenerics; use proc_macro2::{TokenStream, TokenTree}; use quote::{ToTokens, quote}; use syn::parse::{Parse, ParseStream}; @@ -5,7 +6,6 @@ use syn::punctuated::Punctuated; use syn::token::{Brace, Comma, Dot, Lt}; use syn::{Ident, Type, braced, parse_quote, parse2}; -use crate::parse::ImplGenerics; use crate::symbol::symbol_from_string_spanned; pub struct ComponentPaths { diff --git a/crates/cgp-macro-lib/src/parse/type_spec.rs b/crates/cgp-macro-lib/src/parse/type_spec.rs index 40929ee5..1cd40b95 100644 --- a/crates/cgp-macro-lib/src/parse/type_spec.rs +++ b/crates/cgp-macro-lib/src/parse/type_spec.rs @@ -1,10 +1,9 @@ +use cgp_macro_core::types::ImplGenerics; use quote::ToTokens; use syn::Ident; use syn::parse::{Parse, ParseStream}; use syn::token::Lt; -use crate::parse::ImplGenerics; - pub struct TypeSpec { pub name: Ident, pub generics: Option, diff --git a/crates/cgp-macro-lib/src/preset/impl_is_preset.rs b/crates/cgp-macro-lib/src/preset/impl_is_preset.rs index af083209..3daa0632 100644 --- a/crates/cgp-macro-lib/src/preset/impl_is_preset.rs +++ b/crates/cgp-macro-lib/src/preset/impl_is_preset.rs @@ -1,10 +1,11 @@ use alloc::vec::Vec; +use cgp_macro_core::types::ImplGenerics; use syn::punctuated::Punctuated; use syn::token::Comma; use syn::{Ident, ItemImpl, Type, parse_quote}; -use crate::parse::{DelegateEntry, DelegateKey, ImplGenerics, SimpleType}; +use crate::parse::{DelegateEntry, DelegateKey, SimpleType}; pub fn impl_components_is_preset( trait_name: &Ident, From 5bff57075b4a81633862c5bebf9ca7991075976e Mon Sep 17 00:00:00 2001 From: Soares Chen Date: Sun, 17 May 2026 23:20:17 +0200 Subject: [PATCH 12/81] Use PathElement in PathHead --- crates/cgp-macro-core/src/types/path/mod.rs | 4 +- .../path/{nested_path.rs => path_head.rs} | 0 crates/cgp-macro-lib/src/parse/path.rs | 102 ++++-------------- 3 files changed, 24 insertions(+), 82 deletions(-) rename crates/cgp-macro-core/src/types/path/{nested_path.rs => path_head.rs} (100%) diff --git a/crates/cgp-macro-core/src/types/path/mod.rs b/crates/cgp-macro-core/src/types/path/mod.rs index 5f913922..2425a44f 100644 --- a/crates/cgp-macro-core/src/types/path/mod.rs +++ b/crates/cgp-macro-core/src/types/path/mod.rs @@ -1,7 +1,7 @@ -mod nested_path; mod path_element; +mod path_head; mod unipath; -pub use nested_path::*; pub use path_element::*; +pub use path_head::*; pub use unipath::*; diff --git a/crates/cgp-macro-core/src/types/path/nested_path.rs b/crates/cgp-macro-core/src/types/path/path_head.rs similarity index 100% rename from crates/cgp-macro-core/src/types/path/nested_path.rs rename to crates/cgp-macro-core/src/types/path/path_head.rs diff --git a/crates/cgp-macro-lib/src/parse/path.rs b/crates/cgp-macro-lib/src/parse/path.rs index fe6c2d18..8e3f08c9 100644 --- a/crates/cgp-macro-lib/src/parse/path.rs +++ b/crates/cgp-macro-lib/src/parse/path.rs @@ -1,12 +1,10 @@ -use cgp_macro_core::types::ImplGenerics; -use proc_macro2::{TokenStream, TokenTree}; +use cgp_macro_core::types::{ImplGenerics, PathElement}; +use proc_macro2::TokenStream; use quote::{ToTokens, quote}; use syn::parse::{Parse, ParseStream}; use syn::punctuated::Punctuated; use syn::token::{Brace, Comma, Dot, Lt}; -use syn::{Ident, Type, braced, parse_quote, parse2}; - -use crate::symbol::symbol_from_string_spanned; +use syn::{Type, braced, parse_quote}; pub struct ComponentPaths { pub paths: Vec>, @@ -25,7 +23,7 @@ impl Parse for ComponentPaths { let mut paths = Vec::new(); - for path in path_head.to_paths() { + for path in path_head_to_prefix(&path_head) { let path_type: Type = syn::parse2(path.path_type)?; paths.push(ComponentPath { path_type, @@ -43,30 +41,27 @@ pub struct ComponentPath { } pub enum PathHead { - Type(Option, Box, Box), + Type(Option, Box, Box), Group(Punctuated), Wildcard, } -impl PathHead { - pub fn to_paths(&self) -> Vec> { - match self { - Self::Type(generics, path_type, rest) => { - let rest_types = rest.to_paths(); - - prepend_path( - path_type.path_type.to_token_stream(), - generics.clone(), - rest_types, - ) - } - Self::Group(paths) => paths.iter().flat_map(|path| path.to_paths()).collect(), - Self::Wildcard => { - vec![ComponentPath { - path_type: quote! { __Wildcard__ }, - generics: parse_quote! { <__Wildcard__> }, - }] - } +pub fn path_head_to_prefix(path_head: &PathHead) -> Vec> { + match path_head { + PathHead::Type(generics, path_type, rest) => { + let rest_types = path_head_to_prefix(rest); + + prepend_path(path_type.to_token_stream(), generics.clone(), rest_types) + } + PathHead::Group(paths) => paths + .iter() + .flat_map(|path| path_head_to_prefix(path)) + .collect(), + PathHead::Wildcard => { + vec![ComponentPath { + path_type: quote! { __Wildcard__ }, + generics: parse_quote! { <__Wildcard__> }, + }] } } } @@ -115,7 +110,7 @@ impl Parse for PathHead { None }; - let path_type: PathType = input.parse()?; + let path_type: PathElement = input.parse()?; let rest_path = if input.peek(Dot) { let _: Dot = input.parse()?; @@ -128,56 +123,3 @@ impl Parse for PathHead { } } } - -pub fn path_type_as_ident(path_type: &Type) -> Option { - let path_tokens = path_type.to_token_stream().into_iter().collect::>(); - let [path_token]: [TokenTree; 1] = path_tokens.try_into().ok()?; - - if let TokenTree::Ident(path_ident) = path_token { - let path_str = path_ident.to_string(); - if let Some(path_char) = path_str.chars().next() - && path_char.is_ascii_lowercase() - && !is_primitive_type(&path_str) - { - return Some(path_ident); - } - } - - None -} - -pub struct PathType { - pub path_type: Type, -} - -impl Parse for PathType { - fn parse(input: ParseStream) -> syn::Result { - let path_type: Type = input.parse()?; - - if let Some(path_ident) = path_type_as_ident(&path_type) { - let path_symbol = parse2(symbol_from_string_spanned( - path_ident.span(), - &path_ident.to_string(), - ))?; - Ok(Self { - path_type: path_symbol, - }) - } else { - Ok(Self { path_type }) - } - } -} - -pub fn is_primitive_type(ident: &str) -> bool { - if (ident.starts_with("i") || ident.starts_with("u") || ident.starts_with("f")) - && ident[1..].chars().all(|c| c.is_numeric()) - { - return true; - } - - if ["char", "bool", "usize", "isize", "str"].contains(&ident) { - return true; - } - - false -} From 55a669543c14d1714acdb1361cfcdcdc638f1e8e Mon Sep 17 00:00:00 2001 From: Soares Chen Date: Sun, 17 May 2026 23:23:37 +0200 Subject: [PATCH 13/81] Move PathHead --- .../src/types/path/path_head.rs | 43 ++++++++++++++++++ crates/cgp-macro-lib/src/parse/path.rs | 44 +------------------ 2 files changed, 45 insertions(+), 42 deletions(-) diff --git a/crates/cgp-macro-core/src/types/path/path_head.rs b/crates/cgp-macro-core/src/types/path/path_head.rs index 8b137891..87635114 100644 --- a/crates/cgp-macro-core/src/types/path/path_head.rs +++ b/crates/cgp-macro-core/src/types/path/path_head.rs @@ -1 +1,44 @@ +use syn::braced; +use syn::parse::{Parse, ParseStream}; +use syn::punctuated::Punctuated; +use syn::token::{Brace, Comma, Dot, Lt}; +use crate::types::{ImplGenerics, PathElement}; + +pub enum PathHead { + Type(Option, Box, Box), + Group(Punctuated), + Wildcard, +} + +impl Parse for PathHead { + fn parse(input: ParseStream) -> syn::Result { + if input.is_empty() { + Ok(Self::Wildcard) + } else if input.peek(Brace) { + let body; + braced!(body in input); + + let group = Punctuated::parse_terminated(&body)?; + + Ok(Self::Group(group)) + } else { + let generics = if input.peek(Lt) { + Some(input.parse()?) + } else { + None + }; + + let path_type: PathElement = input.parse()?; + + let rest_path = if input.peek(Dot) { + let _: Dot = input.parse()?; + Box::new(Self::parse(input)?) + } else { + Box::new(Self::Wildcard) + }; + + Ok(Self::Type(generics, Box::new(path_type), rest_path)) + } + } +} diff --git a/crates/cgp-macro-lib/src/parse/path.rs b/crates/cgp-macro-lib/src/parse/path.rs index 8e3f08c9..1cd91f40 100644 --- a/crates/cgp-macro-lib/src/parse/path.rs +++ b/crates/cgp-macro-lib/src/parse/path.rs @@ -1,10 +1,8 @@ -use cgp_macro_core::types::{ImplGenerics, PathElement}; +use cgp_macro_core::types::{ImplGenerics, PathHead}; use proc_macro2::TokenStream; use quote::{ToTokens, quote}; use syn::parse::{Parse, ParseStream}; -use syn::punctuated::Punctuated; -use syn::token::{Brace, Comma, Dot, Lt}; -use syn::{Type, braced, parse_quote}; +use syn::{Type, parse_quote}; pub struct ComponentPaths { pub paths: Vec>, @@ -40,12 +38,6 @@ pub struct ComponentPath { pub generics: ImplGenerics, } -pub enum PathHead { - Type(Option, Box, Box), - Group(Punctuated), - Wildcard, -} - pub fn path_head_to_prefix(path_head: &PathHead) -> Vec> { match path_head { PathHead::Type(generics, path_type, rest) => { @@ -91,35 +83,3 @@ pub fn prepend_path( }) .collect() } - -impl Parse for PathHead { - fn parse(input: ParseStream) -> syn::Result { - if input.is_empty() { - Ok(Self::Wildcard) - } else if input.peek(Brace) { - let body; - braced!(body in input); - - let group = Punctuated::parse_terminated(&body)?; - - Ok(Self::Group(group)) - } else { - let generics = if input.peek(Lt) { - Some(input.parse()?) - } else { - None - }; - - let path_type: PathElement = input.parse()?; - - let rest_path = if input.peek(Dot) { - let _: Dot = input.parse()?; - Box::new(Self::parse(input)?) - } else { - Box::new(Self::Wildcard) - }; - - Ok(Self::Type(generics, Box::new(path_type), rest_path)) - } - } -} From 0d9d72916116b2de8d5738712596a7f7dd9173c8 Mon Sep 17 00:00:00 2001 From: Soares Chen Date: Sun, 17 May 2026 23:26:25 +0200 Subject: [PATCH 14/81] Refactor PathHead --- .../cgp-macro-core/src/types/path/path_head.rs | 16 ++++++---------- crates/cgp-macro-lib/src/parse/path.rs | 16 +++++++--------- 2 files changed, 13 insertions(+), 19 deletions(-) diff --git a/crates/cgp-macro-core/src/types/path/path_head.rs b/crates/cgp-macro-core/src/types/path/path_head.rs index 87635114..66c82df6 100644 --- a/crates/cgp-macro-core/src/types/path/path_head.rs +++ b/crates/cgp-macro-core/src/types/path/path_head.rs @@ -1,20 +1,20 @@ use syn::braced; use syn::parse::{Parse, ParseStream}; use syn::punctuated::Punctuated; -use syn::token::{Brace, Comma, Dot, Lt}; +use syn::token::{Brace, Comma, Dot}; use crate::types::{ImplGenerics, PathElement}; pub enum PathHead { - Type(Option, Box, Box), + Type(ImplGenerics, Box, Box), Group(Punctuated), - Wildcard, + End, } impl Parse for PathHead { fn parse(input: ParseStream) -> syn::Result { if input.is_empty() { - Ok(Self::Wildcard) + Ok(Self::End) } else if input.peek(Brace) { let body; braced!(body in input); @@ -23,11 +23,7 @@ impl Parse for PathHead { Ok(Self::Group(group)) } else { - let generics = if input.peek(Lt) { - Some(input.parse()?) - } else { - None - }; + let generics = input.parse()?; let path_type: PathElement = input.parse()?; @@ -35,7 +31,7 @@ impl Parse for PathHead { let _: Dot = input.parse()?; Box::new(Self::parse(input)?) } else { - Box::new(Self::Wildcard) + Box::new(Self::End) }; Ok(Self::Type(generics, Box::new(path_type), rest_path)) diff --git a/crates/cgp-macro-lib/src/parse/path.rs b/crates/cgp-macro-lib/src/parse/path.rs index 1cd91f40..72b1894a 100644 --- a/crates/cgp-macro-lib/src/parse/path.rs +++ b/crates/cgp-macro-lib/src/parse/path.rs @@ -12,7 +12,7 @@ impl Parse for ComponentPaths { fn parse(input: ParseStream) -> syn::Result { let path_head = PathHead::parse(input)?; - if let PathHead::Wildcard = path_head { + if let PathHead::End = path_head { return Err(syn::Error::new( input.span(), "Expected at least one path element", @@ -49,7 +49,7 @@ pub fn path_head_to_prefix(path_head: &PathHead) -> Vec { + PathHead::End => { vec![ComponentPath { path_type: quote! { __Wildcard__ }, generics: parse_quote! { <__Wildcard__> }, @@ -60,7 +60,7 @@ pub fn path_head_to_prefix(path_head: &PathHead) -> Vec, + generics: ImplGenerics, rest_types: Vec>, ) -> Vec> { rest_types @@ -68,12 +68,10 @@ pub fn prepend_path( .map(|mut path| { let rest_tokens = path.path_type; - if let Some(generics) = &generics { - path.generics - .generics - .params - .extend(generics.generics.params.clone()); - } + path.generics + .generics + .params + .extend(generics.generics.params.clone()); let new_path = quote! { PathCons< #path_type , #rest_tokens > }; ComponentPath { From 39d37a7a735a913c1844593ecbd46eab16bbd154 Mon Sep 17 00:00:00 2001 From: Soares Chen Date: Sun, 17 May 2026 23:49:41 +0200 Subject: [PATCH 15/81] Implement PathHead::into_paths --- .../cgp-macro-core/src/types/impl_generics.rs | 8 ++++- .../src/types/path/path_element.rs | 1 + .../src/types/path/path_head.rs | 29 ++++++++++++++++++- .../cgp-macro-core/src/types/path/unipath.rs | 7 +++++ crates/cgp-macro-core/src/types/symbol.rs | 1 + 5 files changed, 44 insertions(+), 2 deletions(-) diff --git a/crates/cgp-macro-core/src/types/impl_generics.rs b/crates/cgp-macro-core/src/types/impl_generics.rs index 71417e52..8b760971 100644 --- a/crates/cgp-macro-core/src/types/impl_generics.rs +++ b/crates/cgp-macro-core/src/types/impl_generics.rs @@ -1,4 +1,4 @@ -use core::ops::Deref; +use core::ops::{Deref, DerefMut}; use proc_macro2::TokenStream; use quote::ToTokens; @@ -18,6 +18,12 @@ impl Deref for ImplGenerics { } } +impl DerefMut for ImplGenerics { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.generics + } +} + impl Parse for ImplGenerics { fn parse(input: ParseStream) -> syn::Result { let generics: Generics = input.parse()?; diff --git a/crates/cgp-macro-core/src/types/path/path_element.rs b/crates/cgp-macro-core/src/types/path/path_element.rs index cc35f059..2e5d8afc 100644 --- a/crates/cgp-macro-core/src/types/path/path_element.rs +++ b/crates/cgp-macro-core/src/types/path/path_element.rs @@ -6,6 +6,7 @@ use syn::{Ident, Type, parse2}; use crate::traits::ToType; use crate::types::symbol::Symbol; +#[derive(Debug, Clone)] pub enum PathElement { Type(Type), Symbol(Symbol), diff --git a/crates/cgp-macro-core/src/types/path/path_head.rs b/crates/cgp-macro-core/src/types/path/path_head.rs index 66c82df6..8e462c61 100644 --- a/crates/cgp-macro-core/src/types/path/path_head.rs +++ b/crates/cgp-macro-core/src/types/path/path_head.rs @@ -3,7 +3,7 @@ use syn::parse::{Parse, ParseStream}; use syn::punctuated::Punctuated; use syn::token::{Brace, Comma, Dot}; -use crate::types::{ImplGenerics, PathElement}; +use crate::types::{ImplGenerics, PathElement, UniPath}; pub enum PathHead { Type(ImplGenerics, Box, Box), @@ -11,6 +11,33 @@ pub enum PathHead { End, } +impl PathHead { + pub fn into_paths(&self, suffix_path: &UniPath) -> Vec<(ImplGenerics, UniPath)> { + match self { + Self::Type(generics, path_element, tail) => { + let tail_paths = tail.into_paths(suffix_path); + let mut out_paths = Vec::new(); + + for (tail_generics, mut tail_path) in tail_paths { + let mut generics = generics.clone(); + generics.params.extend(tail_generics.params.iter().cloned()); + tail_path.elements.insert(0, path_element.as_ref().clone()); + out_paths.push((generics, tail_path)) + } + + out_paths + } + Self::Group(path_heads) => path_heads + .iter() + .flat_map(|path| path.into_paths(suffix_path)) + .collect(), + Self::End => { + vec![(ImplGenerics::default(), suffix_path.clone())] + } + } + } +} + impl Parse for PathHead { fn parse(input: ParseStream) -> syn::Result { if input.is_empty() { diff --git a/crates/cgp-macro-core/src/types/path/unipath.rs b/crates/cgp-macro-core/src/types/path/unipath.rs index 89b57bbe..70bdcd8b 100644 --- a/crates/cgp-macro-core/src/types/path/unipath.rs +++ b/crates/cgp-macro-core/src/types/path/unipath.rs @@ -8,11 +8,18 @@ use syn::token::{At, Dot}; use crate::exports::{Nil, PathCons}; use crate::types::path::PathElement; +#[derive(Debug, Clone)] pub struct UniPath { pub elements: Punctuated, } impl UniPath { + pub fn from_iter(elements: impl IntoIterator) -> Self { + Self { + elements: Punctuated::from_iter(elements), + } + } + pub fn append_type(&mut self, ty: Type) { self.elements.push(PathElement::Type(ty)); } diff --git a/crates/cgp-macro-core/src/types/symbol.rs b/crates/cgp-macro-core/src/types/symbol.rs index b6f51ddb..e7081e47 100644 --- a/crates/cgp-macro-core/src/types/symbol.rs +++ b/crates/cgp-macro-core/src/types/symbol.rs @@ -4,6 +4,7 @@ use syn::{Ident, Type, parse_quote}; use crate::traits::ToType; +#[derive(Debug, Clone)] pub struct Symbol { pub ident: Ident, } From 8e7a48e08567c5bb90c906983474c425ef12050f Mon Sep 17 00:00:00 2001 From: Soares Chen Date: Sun, 17 May 2026 23:53:51 +0200 Subject: [PATCH 16/81] Implement NonEmptyPathHead --- .../cgp-macro-core/src/types/impl_generics.rs | 2 +- crates/cgp-macro-core/src/types/path/mod.rs | 2 ++ .../src/types/path/non_empty_head.rs | 33 +++++++++++++++++++ .../src/types/path/path_head.rs | 9 ++--- .../cgp-macro-core/src/types/path/unipath.rs | 2 +- 5 files changed, 42 insertions(+), 6 deletions(-) create mode 100644 crates/cgp-macro-core/src/types/path/non_empty_head.rs diff --git a/crates/cgp-macro-core/src/types/impl_generics.rs b/crates/cgp-macro-core/src/types/impl_generics.rs index 8b760971..614b50b1 100644 --- a/crates/cgp-macro-core/src/types/impl_generics.rs +++ b/crates/cgp-macro-core/src/types/impl_generics.rs @@ -5,7 +5,7 @@ use quote::ToTokens; use syn::parse::{Parse, ParseStream}; use syn::{Error, Generics, parse2}; -#[derive(Clone, Default)] +#[derive(Debug, Clone, Default)] pub struct ImplGenerics { pub generics: Generics, } diff --git a/crates/cgp-macro-core/src/types/path/mod.rs b/crates/cgp-macro-core/src/types/path/mod.rs index 2425a44f..233f69f1 100644 --- a/crates/cgp-macro-core/src/types/path/mod.rs +++ b/crates/cgp-macro-core/src/types/path/mod.rs @@ -1,7 +1,9 @@ +mod non_empty_head; mod path_element; mod path_head; mod unipath; +pub use non_empty_head::*; pub use path_element::*; pub use path_head::*; pub use unipath::*; diff --git a/crates/cgp-macro-core/src/types/path/non_empty_head.rs b/crates/cgp-macro-core/src/types/path/non_empty_head.rs new file mode 100644 index 00000000..2ede9ff3 --- /dev/null +++ b/crates/cgp-macro-core/src/types/path/non_empty_head.rs @@ -0,0 +1,33 @@ +use core::ops::Deref; + +use syn::parse::{Parse, ParseStream}; + +use crate::types::PathHead; + +#[derive(Debug, Clone)] +pub struct NonEmptyPathHead { + pub path_head: PathHead, +} + +impl Deref for NonEmptyPathHead { + type Target = PathHead; + + fn deref(&self) -> &Self::Target { + &self.path_head + } +} + +impl Parse for NonEmptyPathHead { + fn parse(input: ParseStream) -> syn::Result { + let path_head = input.parse()?; + + if let PathHead::End = path_head { + return Err(syn::Error::new( + input.span(), + "Expected at least one path element", + )); + } + + Ok(Self { path_head }) + } +} diff --git a/crates/cgp-macro-core/src/types/path/path_head.rs b/crates/cgp-macro-core/src/types/path/path_head.rs index 8e462c61..a9dccea8 100644 --- a/crates/cgp-macro-core/src/types/path/path_head.rs +++ b/crates/cgp-macro-core/src/types/path/path_head.rs @@ -5,6 +5,7 @@ use syn::token::{Brace, Comma, Dot}; use crate::types::{ImplGenerics, PathElement, UniPath}; +#[derive(Debug, Clone)] pub enum PathHead { Type(ImplGenerics, Box, Box), Group(Punctuated), @@ -12,10 +13,10 @@ pub enum PathHead { } impl PathHead { - pub fn into_paths(&self, suffix_path: &UniPath) -> Vec<(ImplGenerics, UniPath)> { + pub fn into_paths(&self) -> Vec<(ImplGenerics, UniPath)> { match self { Self::Type(generics, path_element, tail) => { - let tail_paths = tail.into_paths(suffix_path); + let tail_paths = tail.into_paths(); let mut out_paths = Vec::new(); for (tail_generics, mut tail_path) in tail_paths { @@ -29,10 +30,10 @@ impl PathHead { } Self::Group(path_heads) => path_heads .iter() - .flat_map(|path| path.into_paths(suffix_path)) + .flat_map(|path| path.into_paths()) .collect(), Self::End => { - vec![(ImplGenerics::default(), suffix_path.clone())] + vec![(ImplGenerics::default(), UniPath::default())] } } } diff --git a/crates/cgp-macro-core/src/types/path/unipath.rs b/crates/cgp-macro-core/src/types/path/unipath.rs index 70bdcd8b..1be16de6 100644 --- a/crates/cgp-macro-core/src/types/path/unipath.rs +++ b/crates/cgp-macro-core/src/types/path/unipath.rs @@ -8,7 +8,7 @@ use syn::token::{At, Dot}; use crate::exports::{Nil, PathCons}; use crate::types::path::PathElement; -#[derive(Debug, Clone)] +#[derive(Debug, Clone, Default)] pub struct UniPath { pub elements: Punctuated, } From 03891d2f4f1df0b6260e946a5403926974c3380e Mon Sep 17 00:00:00 2001 From: Soares Chen Date: Mon, 18 May 2026 00:04:43 +0200 Subject: [PATCH 17/81] Implement PathHeadOrType --- crates/cgp-macro-core/src/types/path/mod.rs | 4 +-- .../src/types/path/non_empty_head.rs | 33 ------------------- .../src/types/path/path_head_or_type.rs | 26 +++++++++++++++ 3 files changed, 28 insertions(+), 35 deletions(-) delete mode 100644 crates/cgp-macro-core/src/types/path/non_empty_head.rs create mode 100644 crates/cgp-macro-core/src/types/path/path_head_or_type.rs diff --git a/crates/cgp-macro-core/src/types/path/mod.rs b/crates/cgp-macro-core/src/types/path/mod.rs index 233f69f1..9a5d992b 100644 --- a/crates/cgp-macro-core/src/types/path/mod.rs +++ b/crates/cgp-macro-core/src/types/path/mod.rs @@ -1,9 +1,9 @@ -mod non_empty_head; mod path_element; mod path_head; +mod path_head_or_type; mod unipath; -pub use non_empty_head::*; pub use path_element::*; pub use path_head::*; +pub use path_head_or_type::*; pub use unipath::*; diff --git a/crates/cgp-macro-core/src/types/path/non_empty_head.rs b/crates/cgp-macro-core/src/types/path/non_empty_head.rs deleted file mode 100644 index 2ede9ff3..00000000 --- a/crates/cgp-macro-core/src/types/path/non_empty_head.rs +++ /dev/null @@ -1,33 +0,0 @@ -use core::ops::Deref; - -use syn::parse::{Parse, ParseStream}; - -use crate::types::PathHead; - -#[derive(Debug, Clone)] -pub struct NonEmptyPathHead { - pub path_head: PathHead, -} - -impl Deref for NonEmptyPathHead { - type Target = PathHead; - - fn deref(&self) -> &Self::Target { - &self.path_head - } -} - -impl Parse for NonEmptyPathHead { - fn parse(input: ParseStream) -> syn::Result { - let path_head = input.parse()?; - - if let PathHead::End = path_head { - return Err(syn::Error::new( - input.span(), - "Expected at least one path element", - )); - } - - Ok(Self { path_head }) - } -} diff --git a/crates/cgp-macro-core/src/types/path/path_head_or_type.rs b/crates/cgp-macro-core/src/types/path/path_head_or_type.rs new file mode 100644 index 00000000..979da021 --- /dev/null +++ b/crates/cgp-macro-core/src/types/path/path_head_or_type.rs @@ -0,0 +1,26 @@ +use syn::parse::{Parse, ParseStream}; +use syn::token::{At, Type}; + +use crate::types::{ImplGenerics, PathHead}; + +#[derive(Debug, Clone)] +pub enum PathHeadOrType { + PathHead(PathHead), + Type(ImplGenerics, Type), +} + +impl Parse for PathHeadOrType { + fn parse(input: ParseStream) -> syn::Result { + if input.peek(At) { + let _: At = input.parse()?; + + let path_head = input.parse()?; + + Ok(Self::PathHead(path_head)) + } else { + let generics = input.parse()?; + let ty = input.parse()?; + Ok(Self::Type(generics, ty)) + } + } +} From 1a4a9c45db9522c5c12f8bb2ef0f8066afef5ec0 Mon Sep 17 00:00:00 2001 From: Soares Chen Date: Mon, 18 May 2026 00:25:47 +0200 Subject: [PATCH 18/81] Use PathHeadOrType in NamespaceSpec --- crates/cgp-macro-core/src/types/path/mod.rs | 2 + .../src/types/path/path_head_or_type.rs | 3 +- .../cgp-macro-core/src/types/path/prefix.rs | 25 +++++ .../cgp-macro-core/src/types/path/unipath.rs | 8 +- .../cgp-macro-lib/src/cgp_namespace/derive.rs | 97 ++++++++++++++----- .../cgp-macro-lib/src/cgp_namespace/spec.rs | 31 +----- 6 files changed, 114 insertions(+), 52 deletions(-) create mode 100644 crates/cgp-macro-core/src/types/path/prefix.rs diff --git a/crates/cgp-macro-core/src/types/path/mod.rs b/crates/cgp-macro-core/src/types/path/mod.rs index 9a5d992b..7537b012 100644 --- a/crates/cgp-macro-core/src/types/path/mod.rs +++ b/crates/cgp-macro-core/src/types/path/mod.rs @@ -1,9 +1,11 @@ mod path_element; mod path_head; mod path_head_or_type; +mod prefix; mod unipath; pub use path_element::*; pub use path_head::*; pub use path_head_or_type::*; +pub use prefix::*; pub use unipath::*; diff --git a/crates/cgp-macro-core/src/types/path/path_head_or_type.rs b/crates/cgp-macro-core/src/types/path/path_head_or_type.rs index 979da021..1292272d 100644 --- a/crates/cgp-macro-core/src/types/path/path_head_or_type.rs +++ b/crates/cgp-macro-core/src/types/path/path_head_or_type.rs @@ -1,5 +1,6 @@ +use syn::Type; use syn::parse::{Parse, ParseStream}; -use syn::token::{At, Type}; +use syn::token::At; use crate::types::{ImplGenerics, PathHead}; diff --git a/crates/cgp-macro-core/src/types/path/prefix.rs b/crates/cgp-macro-core/src/types/path/prefix.rs new file mode 100644 index 00000000..5d1b4268 --- /dev/null +++ b/crates/cgp-macro-core/src/types/path/prefix.rs @@ -0,0 +1,25 @@ +use proc_macro2::TokenStream; +use quote::{ToTokens, quote}; +use syn::Type; +use syn::punctuated::Punctuated; +use syn::token::Dot; + +use crate::exports::PathCons; +use crate::types::path::PathElement; + +#[derive(Debug, Clone)] +pub struct PrefixPath { + pub elements: Punctuated, + pub suffix: Type, +} + +impl ToTokens for PrefixPath { + fn to_tokens(&self, tokens: &mut TokenStream) { + let out = self.elements.iter().rev().fold( + self.suffix.to_token_stream(), + |acc, current| quote!( #PathCons < #current, #acc > ), + ); + + tokens.extend(out) + } +} diff --git a/crates/cgp-macro-core/src/types/path/unipath.rs b/crates/cgp-macro-core/src/types/path/unipath.rs index 1be16de6..31477ba3 100644 --- a/crates/cgp-macro-core/src/types/path/unipath.rs +++ b/crates/cgp-macro-core/src/types/path/unipath.rs @@ -6,6 +6,7 @@ use syn::punctuated::Punctuated; use syn::token::{At, Dot}; use crate::exports::{Nil, PathCons}; +use crate::types::PrefixPath; use crate::types::path::PathElement; #[derive(Debug, Clone, Default)] @@ -20,8 +21,11 @@ impl UniPath { } } - pub fn append_type(&mut self, ty: Type) { - self.elements.push(PathElement::Type(ty)); + pub fn to_prefix(self, suffix: Type) -> PrefixPath { + PrefixPath { + elements: self.elements, + suffix, + } } } diff --git a/crates/cgp-macro-lib/src/cgp_namespace/derive.rs b/crates/cgp-macro-lib/src/cgp_namespace/derive.rs index 229af26b..c72b1b03 100644 --- a/crates/cgp-macro-lib/src/cgp_namespace/derive.rs +++ b/crates/cgp-macro-lib/src/cgp_namespace/derive.rs @@ -1,3 +1,4 @@ +use cgp_macro_core::types::PathHeadOrType; use proc_macro2::TokenStream; use quote::quote; use syn::{Ident, ItemImpl, ItemStruct, ItemTrait, parse_quote, parse2}; @@ -50,32 +51,82 @@ pub fn derive_namespace(spec: NamespaceSpec) -> syn::Result { for entry in spec.entries.into_iter() { let value = entry.value; - // value.append_type(parse_quote!(__Wildcard__)); - - for path in entry.keys.paths.into_iter() { - let path_type = path.path_type; - - let mut generics = path.generics.generics; - generics.params.push(parse_quote!(__Components__)); - let impl_generics = generics.split_for_impl().0; - - let item_impl: ItemImpl = parse2(quote! { - impl #impl_generics - #namespace_ident< __Components__ > - for #path_type - { - type Provider = RedirectLookup< - __Components__, - #value, - >; + match entry.keys { + PathHeadOrType::PathHead(path_head) => { + for (mut generics, path) in path_head.into_paths() { + generics.params.push(parse_quote!(__Components__)); + generics.params.push(parse_quote!(__Wildcard__)); + + let prefix = path.to_prefix(parse_quote!(__Wildcard__)); + + let impl_generics = generics.split_for_impl().0; + + let item_impl: ItemImpl = parse2(quote! { + impl #impl_generics + #namespace_ident< __Components__ > + for #prefix + { + type Provider = RedirectLookup< + __Components__, + #value, + >; + } + })?; + + out.extend(quote! { + #item_impl + }) } - })?; - - out.extend(quote! { - #item_impl - }) + } + PathHeadOrType::Type(mut generics, ty) => { + generics.params.push(parse_quote!(__Components__)); + let impl_generics = generics.split_for_impl().0; + + let item_impl: ItemImpl = parse2(quote! { + impl #impl_generics + #namespace_ident< __Components__ > + for #ty + { + type Provider = RedirectLookup< + __Components__, + #value, + >; + } + })?; + + out.extend(quote! { + #item_impl + }) + } } + + // value.append_type(parse_quote!(__Wildcard__)); + + // for path in entry.keys.paths.into_iter() { + // let path_type = path.path_type; + + // let mut generics = path.generics.generics; + // generics.params.push(parse_quote!(__Components__)); + + // let impl_generics = generics.split_for_impl().0; + + // let item_impl: ItemImpl = parse2(quote! { + // impl #impl_generics + // #namespace_ident< __Components__ > + // for #path_type + // { + // type Provider = RedirectLookup< + // __Components__, + // #value, + // >; + // } + // })?; + + // out.extend(quote! { + // #item_impl + // }) + // } } Ok(out) diff --git a/crates/cgp-macro-lib/src/cgp_namespace/spec.rs b/crates/cgp-macro-lib/src/cgp_namespace/spec.rs index 89859be8..62450912 100644 --- a/crates/cgp-macro-lib/src/cgp_namespace/spec.rs +++ b/crates/cgp-macro-lib/src/cgp_namespace/spec.rs @@ -1,10 +1,8 @@ -use cgp_macro_core::types::{ImplGenerics, UniPath}; +use cgp_macro_core::types::{PathHeadOrType, UniPath}; use syn::parse::{Parse, ParseStream}; use syn::punctuated::Punctuated; -use syn::token::{At, Colon, Comma, Lt}; -use syn::{Ident, Type, braced}; - -use crate::parse::{ComponentPath, ComponentPaths}; +use syn::token::{Colon, Comma}; +use syn::{Ident, braced}; pub struct NamespaceSpec { pub namespace_ident: Ident, @@ -13,7 +11,7 @@ pub struct NamespaceSpec { } pub struct NamespaceEntry { - pub keys: ComponentPaths, + pub keys: PathHeadOrType, pub value: UniPath, } @@ -44,26 +42,7 @@ impl Parse for NamespaceSpec { impl Parse for NamespaceEntry { fn parse(input: ParseStream) -> syn::Result { - let keys: ComponentPaths = if input.peek(At) { - let _: At = input.parse()?; - - input.parse()? - } else { - let generics: ImplGenerics = if input.peek(Lt) { - input.parse()? - } else { - Default::default() - }; - - let path_type: Type = input.parse()?; - - let path = ComponentPath { - generics, - path_type, - }; - - ComponentPaths { paths: vec![path] } - }; + let keys = input.parse()?; let _: Colon = input.parse()?; From 56b08dba1c81e288ba902faaf37a06e9248af43d Mon Sep 17 00:00:00 2001 From: Soares Chen Date: Mon, 18 May 2026 00:30:58 +0200 Subject: [PATCH 19/81] Simplify prefix delegation in cgp_namespace --- crates/cgp-macro-lib/src/cgp_namespace/derive.rs | 3 ++- crates/cgp-tests/src/namespaces/extended.rs | 7 ++----- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/crates/cgp-macro-lib/src/cgp_namespace/derive.rs b/crates/cgp-macro-lib/src/cgp_namespace/derive.rs index c72b1b03..efa0413f 100644 --- a/crates/cgp-macro-lib/src/cgp_namespace/derive.rs +++ b/crates/cgp-macro-lib/src/cgp_namespace/derive.rs @@ -61,6 +61,7 @@ pub fn derive_namespace(spec: NamespaceSpec) -> syn::Result { let prefix = path.to_prefix(parse_quote!(__Wildcard__)); let impl_generics = generics.split_for_impl().0; + let redirect_target = value.clone().to_prefix(parse_quote!(__Wildcard__)); let item_impl: ItemImpl = parse2(quote! { impl #impl_generics @@ -69,7 +70,7 @@ pub fn derive_namespace(spec: NamespaceSpec) -> syn::Result { { type Provider = RedirectLookup< __Components__, - #value, + #redirect_target, >; } })?; diff --git a/crates/cgp-tests/src/namespaces/extended.rs b/crates/cgp-tests/src/namespaces/extended.rs index 3c4699e0..bae6e595 100644 --- a/crates/cgp-tests/src/namespaces/extended.rs +++ b/crates/cgp-tests/src/namespaces/extended.rs @@ -1,12 +1,9 @@ use cgp::core::component::RedirectLookup; -use cgp::core::error::{ErrorRaiserComponent, ErrorTypeProviderComponent}; use cgp::prelude::*; cgp_namespace! { ExtendedNamespace: DefaultNamespace { - @cgp.core.error.ErrorRaiserComponent: - @app.ErrorRaiserComponent, - @cgp.core.error.ErrorTypeProviderComponent: - @app.ErrorTypeProviderComponent, + @cgp.core.error: + @app, } } From 0f7bb29f7310b7482dab90e144b88e7f989245fa Mon Sep 17 00:00:00 2001 From: Soares Chen Date: Mon, 18 May 2026 00:36:48 +0200 Subject: [PATCH 20/81] Implicitly append component name in namespace --- crates/cgp-error/src/traits/can_raise_error.rs | 2 +- crates/cgp-error/src/traits/can_wrap_error.rs | 2 +- crates/cgp-error/src/traits/has_error_type.rs | 2 +- crates/cgp-macro-core/src/types/path/unipath.rs | 4 ++++ .../cgp-macro-lib/src/derive_component/derive_namespace.rs | 5 +++-- crates/cgp-tests/tests/namespace_tests/multi_param.rs | 2 +- 6 files changed, 11 insertions(+), 6 deletions(-) diff --git a/crates/cgp-error/src/traits/can_raise_error.rs b/crates/cgp-error/src/traits/can_raise_error.rs index 866757a6..86597ee8 100644 --- a/crates/cgp-error/src/traits/can_raise_error.rs +++ b/crates/cgp-error/src/traits/can_raise_error.rs @@ -11,7 +11,7 @@ use crate::traits::has_error_type::HasErrorType; provider: ErrorRaiser, derive_delegate: UseDelegate, }] -#[namespace(@cgp.core.error.ErrorRaiserComponent)] +#[namespace(@cgp.core.error)] pub trait CanRaiseError: HasErrorType { fn raise_error(error: SourceError) -> Self::Error; } diff --git a/crates/cgp-error/src/traits/can_wrap_error.rs b/crates/cgp-error/src/traits/can_wrap_error.rs index 954b470b..18fa8694 100644 --- a/crates/cgp-error/src/traits/can_wrap_error.rs +++ b/crates/cgp-error/src/traits/can_wrap_error.rs @@ -7,7 +7,7 @@ use crate::traits::HasErrorType; provider: ErrorWrapper, derive_delegate: UseDelegate, }] -#[namespace(@cgp.core.error.ErrorWrapperComponent)] +#[namespace(@cgp.core.error)] pub trait CanWrapError: HasErrorType { fn wrap_error(error: Self::Error, detail: Detail) -> Self::Error; } diff --git a/crates/cgp-error/src/traits/has_error_type.rs b/crates/cgp-error/src/traits/has_error_type.rs index 6cf37ee5..3c1ff664 100644 --- a/crates/cgp-error/src/traits/has_error_type.rs +++ b/crates/cgp-error/src/traits/has_error_type.rs @@ -24,7 +24,7 @@ use cgp_type::{TypeProvider, UseType}; */ #[cgp_type] -#[namespace(@cgp.core.error.ErrorTypeProviderComponent)] +#[namespace(@cgp.core.error)] pub trait HasErrorType { type Error: Debug; } diff --git a/crates/cgp-macro-core/src/types/path/unipath.rs b/crates/cgp-macro-core/src/types/path/unipath.rs index 31477ba3..3507c95d 100644 --- a/crates/cgp-macro-core/src/types/path/unipath.rs +++ b/crates/cgp-macro-core/src/types/path/unipath.rs @@ -21,6 +21,10 @@ impl UniPath { } } + pub fn append_type(&mut self, ty: Type) { + self.elements.push(PathElement::Type(ty)); + } + pub fn to_prefix(self, suffix: Type) -> PrefixPath { PrefixPath { elements: self.elements, diff --git a/crates/cgp-macro-lib/src/derive_component/derive_namespace.rs b/crates/cgp-macro-lib/src/derive_component/derive_namespace.rs index e3dde545..74095f35 100644 --- a/crates/cgp-macro-lib/src/derive_component/derive_namespace.rs +++ b/crates/cgp-macro-lib/src/derive_component/derive_namespace.rs @@ -1,5 +1,5 @@ use quote::quote; -use syn::{Ident, ItemImpl, parse2}; +use syn::{Ident, ItemImpl, parse_quote, parse2}; use crate::attributes::UseNamespaceAttribute; @@ -21,7 +21,8 @@ pub fn derive_namespace_impl( component_name: &Ident, ) -> syn::Result { let namespace = &attribute.namespace; - let path = &attribute.path; + let mut path = attribute.path.clone(); + path.append_type(parse_quote!(#component_name)); let out = quote! { impl<__Components__> #namespace < __Components__ > for #component_name diff --git a/crates/cgp-tests/tests/namespace_tests/multi_param.rs b/crates/cgp-tests/tests/namespace_tests/multi_param.rs index 5fe681e5..eee477ff 100644 --- a/crates/cgp-tests/tests/namespace_tests/multi_param.rs +++ b/crates/cgp-tests/tests/namespace_tests/multi_param.rs @@ -1,7 +1,7 @@ use cgp::prelude::*; #[cgp_component(FooProvider)] -#[namespace(@app.FooProviderComponent)] +#[namespace(@app)] pub trait Foo<'a, T, U> { fn foo(&self, first: &'a T, second: U); } From 1c4c611701f1ef857fcdcedbf16862ddf27e1a4a Mon Sep 17 00:00:00 2001 From: Soares Chen Date: Mon, 18 May 2026 00:54:46 +0200 Subject: [PATCH 21/81] Use `@path in namespace` syntax --- crates/cgp-macro-lib/src/attributes/namespace.rs | 13 ++++++------- .../src/derive_component/attributes.rs | 7 +++---- crates/cgp-tests/tests/namespace_tests/namespace.rs | 2 +- .../tests/namespace_tests/namespace_macro/basic.rs | 2 +- .../namespace_macro/multi_namespace.rs | 4 ++-- .../namespace_tests/namespace_macro/symbol_path.rs | 2 +- .../namespace_tests/namespace_macro/type_path.rs | 2 +- 7 files changed, 15 insertions(+), 17 deletions(-) diff --git a/crates/cgp-macro-lib/src/attributes/namespace.rs b/crates/cgp-macro-lib/src/attributes/namespace.rs index d16bf207..1182a8bb 100644 --- a/crates/cgp-macro-lib/src/attributes/namespace.rs +++ b/crates/cgp-macro-lib/src/attributes/namespace.rs @@ -1,7 +1,7 @@ use cgp_macro_core::types::UniPath; use syn::Ident; use syn::parse::{Parse, ParseStream}; -use syn::token::Colon; +use syn::token::In; pub struct UseNamespaceAttribute { pub namespace: Ident, @@ -10,16 +10,15 @@ pub struct UseNamespaceAttribute { impl Parse for UseNamespaceAttribute { fn parse(input: ParseStream) -> syn::Result { - let namespace = if input.peek2(Colon) { - let namespace = input.parse()?; - let _: Colon = input.parse()?; - namespace + let path = input.parse()?; + + let namespace = if input.peek(In) { + let _: In = input.parse()?; + input.parse()? } else { Ident::new("DefaultNamespace", input.span()) }; - let path = input.parse()?; - Ok(UseNamespaceAttribute { namespace, path }) } } diff --git a/crates/cgp-macro-lib/src/derive_component/attributes.rs b/crates/cgp-macro-lib/src/derive_component/attributes.rs index ff8e5605..d70d872f 100644 --- a/crates/cgp-macro-lib/src/derive_component/attributes.rs +++ b/crates/cgp-macro-lib/src/derive_component/attributes.rs @@ -1,5 +1,6 @@ use core::mem; +use syn::parse::Parse; use syn::punctuated::Punctuated; use syn::token::Comma; use syn::{Attribute, TypeParamBound}; @@ -37,10 +38,8 @@ pub fn parse_component_attributes( parsed_attributes.use_type.extend(use_type_specs); } else if ident == "namespace" { - let namespace_specs = attribute.parse_args_with( - Punctuated::::parse_terminated, - )?; - parsed_attributes.namespace.extend(namespace_specs); + let namespace_specs = attribute.parse_args_with(UseNamespaceAttribute::parse)?; + parsed_attributes.namespace.push(namespace_specs); } else { attributes.push(attribute); } diff --git a/crates/cgp-tests/tests/namespace_tests/namespace.rs b/crates/cgp-tests/tests/namespace_tests/namespace.rs index 3525f4f9..59205465 100644 --- a/crates/cgp-tests/tests/namespace_tests/namespace.rs +++ b/crates/cgp-tests/tests/namespace_tests/namespace.rs @@ -5,7 +5,7 @@ use cgp::prelude::*; pub struct MyComponents; #[cgp_component(FooProvider)] -#[namespace(DefaultNamespace: @app.MyComponents.FooProviderComponent)] +#[namespace(@app.MyComponents.FooProviderComponent in DefaultNamespace)] pub trait Foo { fn foo(&self); } diff --git a/crates/cgp-tests/tests/namespace_tests/namespace_macro/basic.rs b/crates/cgp-tests/tests/namespace_tests/namespace_macro/basic.rs index 4eb8080a..8582a45c 100644 --- a/crates/cgp-tests/tests/namespace_tests/namespace_macro/basic.rs +++ b/crates/cgp-tests/tests/namespace_tests/namespace_macro/basic.rs @@ -13,7 +13,7 @@ cgp_namespace! { } #[cgp_component(BarProvider)] -#[namespace(MyNamespace: @MyBarComponent)] +#[namespace(@MyBarComponent in MyNamespace)] pub trait Bar { fn bar(&self); } diff --git a/crates/cgp-tests/tests/namespace_tests/namespace_macro/multi_namespace.rs b/crates/cgp-tests/tests/namespace_tests/namespace_macro/multi_namespace.rs index a0807142..f59f0b89 100644 --- a/crates/cgp-tests/tests/namespace_tests/namespace_macro/multi_namespace.rs +++ b/crates/cgp-tests/tests/namespace_tests/namespace_macro/multi_namespace.rs @@ -22,8 +22,8 @@ cgp_namespace! { } #[cgp_component(BarProvider)] -#[namespace(MyNamespace: @MyApp.MyBarComponent)] -#[namespace(OtherNamespace: @my_app.MyBarComponent)] +#[namespace(@MyApp.MyBarComponent in MyNamespace)] +#[namespace(@my_app.MyBarComponent in OtherNamespace)] pub trait Bar { fn bar(&self); } diff --git a/crates/cgp-tests/tests/namespace_tests/namespace_macro/symbol_path.rs b/crates/cgp-tests/tests/namespace_tests/namespace_macro/symbol_path.rs index 684949db..8d294aae 100644 --- a/crates/cgp-tests/tests/namespace_tests/namespace_macro/symbol_path.rs +++ b/crates/cgp-tests/tests/namespace_tests/namespace_macro/symbol_path.rs @@ -13,7 +13,7 @@ cgp_namespace! { } #[cgp_component(BarProvider)] -#[namespace(MyNamespace: @my_app.MyBarComponent)] +#[namespace(@my_app.MyBarComponent in MyNamespace)] pub trait Bar { fn bar(&self); } diff --git a/crates/cgp-tests/tests/namespace_tests/namespace_macro/type_path.rs b/crates/cgp-tests/tests/namespace_tests/namespace_macro/type_path.rs index 8b699987..209adaf7 100644 --- a/crates/cgp-tests/tests/namespace_tests/namespace_macro/type_path.rs +++ b/crates/cgp-tests/tests/namespace_tests/namespace_macro/type_path.rs @@ -15,7 +15,7 @@ cgp_namespace! { } #[cgp_component(BarProvider)] -#[namespace(MyNamespace: @MyApp.MyBarComponent)] +#[namespace(@MyApp.MyBarComponent in MyNamespace)] pub trait Bar { fn bar(&self); } From 1fe502de155b2c14131003b1c6b063d19b6f0962 Mon Sep 17 00:00:00 2001 From: Soares Chen Date: Mon, 18 May 2026 00:56:22 +0200 Subject: [PATCH 22/81] Rename #[namespace] to #[prefix] --- crates/cgp-error/src/traits/can_raise_error.rs | 2 +- crates/cgp-error/src/traits/can_wrap_error.rs | 2 +- crates/cgp-error/src/traits/has_error_type.rs | 2 +- crates/cgp-macro-lib/src/derive_component/attributes.rs | 2 +- crates/cgp-tests/tests/namespace_tests/multi_param.rs | 2 +- crates/cgp-tests/tests/namespace_tests/namespace.rs | 2 +- .../cgp-tests/tests/namespace_tests/namespace_macro/basic.rs | 2 +- .../tests/namespace_tests/namespace_macro/multi_namespace.rs | 4 ++-- .../tests/namespace_tests/namespace_macro/symbol_path.rs | 2 +- .../tests/namespace_tests/namespace_macro/type_path.rs | 2 +- crates/cgp-tests/tests/namespace_tests/redirect.rs | 2 +- 11 files changed, 12 insertions(+), 12 deletions(-) diff --git a/crates/cgp-error/src/traits/can_raise_error.rs b/crates/cgp-error/src/traits/can_raise_error.rs index 86597ee8..324834e2 100644 --- a/crates/cgp-error/src/traits/can_raise_error.rs +++ b/crates/cgp-error/src/traits/can_raise_error.rs @@ -11,7 +11,7 @@ use crate::traits::has_error_type::HasErrorType; provider: ErrorRaiser, derive_delegate: UseDelegate, }] -#[namespace(@cgp.core.error)] +#[prefix(@cgp.core.error)] pub trait CanRaiseError: HasErrorType { fn raise_error(error: SourceError) -> Self::Error; } diff --git a/crates/cgp-error/src/traits/can_wrap_error.rs b/crates/cgp-error/src/traits/can_wrap_error.rs index 18fa8694..704157fc 100644 --- a/crates/cgp-error/src/traits/can_wrap_error.rs +++ b/crates/cgp-error/src/traits/can_wrap_error.rs @@ -7,7 +7,7 @@ use crate::traits::HasErrorType; provider: ErrorWrapper, derive_delegate: UseDelegate, }] -#[namespace(@cgp.core.error)] +#[prefix(@cgp.core.error)] pub trait CanWrapError: HasErrorType { fn wrap_error(error: Self::Error, detail: Detail) -> Self::Error; } diff --git a/crates/cgp-error/src/traits/has_error_type.rs b/crates/cgp-error/src/traits/has_error_type.rs index 3c1ff664..ab18343c 100644 --- a/crates/cgp-error/src/traits/has_error_type.rs +++ b/crates/cgp-error/src/traits/has_error_type.rs @@ -24,7 +24,7 @@ use cgp_type::{TypeProvider, UseType}; */ #[cgp_type] -#[namespace(@cgp.core.error)] +#[prefix(@cgp.core.error)] pub trait HasErrorType { type Error: Debug; } diff --git a/crates/cgp-macro-lib/src/derive_component/attributes.rs b/crates/cgp-macro-lib/src/derive_component/attributes.rs index d70d872f..13d2a8f3 100644 --- a/crates/cgp-macro-lib/src/derive_component/attributes.rs +++ b/crates/cgp-macro-lib/src/derive_component/attributes.rs @@ -37,7 +37,7 @@ pub fn parse_component_attributes( } parsed_attributes.use_type.extend(use_type_specs); - } else if ident == "namespace" { + } else if ident == "prefix" { let namespace_specs = attribute.parse_args_with(UseNamespaceAttribute::parse)?; parsed_attributes.namespace.push(namespace_specs); } else { diff --git a/crates/cgp-tests/tests/namespace_tests/multi_param.rs b/crates/cgp-tests/tests/namespace_tests/multi_param.rs index eee477ff..a1f37460 100644 --- a/crates/cgp-tests/tests/namespace_tests/multi_param.rs +++ b/crates/cgp-tests/tests/namespace_tests/multi_param.rs @@ -1,7 +1,7 @@ use cgp::prelude::*; #[cgp_component(FooProvider)] -#[namespace(@app)] +#[prefix(@app)] pub trait Foo<'a, T, U> { fn foo(&self, first: &'a T, second: U); } diff --git a/crates/cgp-tests/tests/namespace_tests/namespace.rs b/crates/cgp-tests/tests/namespace_tests/namespace.rs index 59205465..a16834a5 100644 --- a/crates/cgp-tests/tests/namespace_tests/namespace.rs +++ b/crates/cgp-tests/tests/namespace_tests/namespace.rs @@ -5,7 +5,7 @@ use cgp::prelude::*; pub struct MyComponents; #[cgp_component(FooProvider)] -#[namespace(@app.MyComponents.FooProviderComponent in DefaultNamespace)] +#[prefix(@app.MyComponents.FooProviderComponent in DefaultNamespace)] pub trait Foo { fn foo(&self); } diff --git a/crates/cgp-tests/tests/namespace_tests/namespace_macro/basic.rs b/crates/cgp-tests/tests/namespace_tests/namespace_macro/basic.rs index 8582a45c..4e4d23b0 100644 --- a/crates/cgp-tests/tests/namespace_tests/namespace_macro/basic.rs +++ b/crates/cgp-tests/tests/namespace_tests/namespace_macro/basic.rs @@ -13,7 +13,7 @@ cgp_namespace! { } #[cgp_component(BarProvider)] -#[namespace(@MyBarComponent in MyNamespace)] +#[prefix(@MyBarComponent in MyNamespace)] pub trait Bar { fn bar(&self); } diff --git a/crates/cgp-tests/tests/namespace_tests/namespace_macro/multi_namespace.rs b/crates/cgp-tests/tests/namespace_tests/namespace_macro/multi_namespace.rs index f59f0b89..199bfa0a 100644 --- a/crates/cgp-tests/tests/namespace_tests/namespace_macro/multi_namespace.rs +++ b/crates/cgp-tests/tests/namespace_tests/namespace_macro/multi_namespace.rs @@ -22,8 +22,8 @@ cgp_namespace! { } #[cgp_component(BarProvider)] -#[namespace(@MyApp.MyBarComponent in MyNamespace)] -#[namespace(@my_app.MyBarComponent in OtherNamespace)] +#[prefix(@MyApp.MyBarComponent in MyNamespace)] +#[prefix(@my_app.MyBarComponent in OtherNamespace)] pub trait Bar { fn bar(&self); } diff --git a/crates/cgp-tests/tests/namespace_tests/namespace_macro/symbol_path.rs b/crates/cgp-tests/tests/namespace_tests/namespace_macro/symbol_path.rs index 8d294aae..b840bea4 100644 --- a/crates/cgp-tests/tests/namespace_tests/namespace_macro/symbol_path.rs +++ b/crates/cgp-tests/tests/namespace_tests/namespace_macro/symbol_path.rs @@ -13,7 +13,7 @@ cgp_namespace! { } #[cgp_component(BarProvider)] -#[namespace(@my_app.MyBarComponent in MyNamespace)] +#[prefix(@my_app.MyBarComponent in MyNamespace)] pub trait Bar { fn bar(&self); } diff --git a/crates/cgp-tests/tests/namespace_tests/namespace_macro/type_path.rs b/crates/cgp-tests/tests/namespace_tests/namespace_macro/type_path.rs index 209adaf7..bdf477e5 100644 --- a/crates/cgp-tests/tests/namespace_tests/namespace_macro/type_path.rs +++ b/crates/cgp-tests/tests/namespace_tests/namespace_macro/type_path.rs @@ -15,7 +15,7 @@ cgp_namespace! { } #[cgp_component(BarProvider)] -#[namespace(@MyApp.MyBarComponent in MyNamespace)] +#[prefix(@MyApp.MyBarComponent in MyNamespace)] pub trait Bar { fn bar(&self); } diff --git a/crates/cgp-tests/tests/namespace_tests/redirect.rs b/crates/cgp-tests/tests/namespace_tests/redirect.rs index e941395a..d86dbf45 100644 --- a/crates/cgp-tests/tests/namespace_tests/redirect.rs +++ b/crates/cgp-tests/tests/namespace_tests/redirect.rs @@ -1,7 +1,7 @@ use cgp::prelude::*; #[cgp_component(FooProvider)] -#[namespace(@bar.baz.FooProviderComponent)] +#[prefix(@bar.baz)] pub trait CanDoFoo { fn foo(); } From b1090385f32069b9947f936e0a12c06577c7c95e Mon Sep 17 00:00:00 2001 From: Soares Chen Date: Wed, 20 May 2026 22:35:25 +0200 Subject: [PATCH 23/81] Move TypeGenerics --- crates/cgp-component/src/lib.rs | 2 +- crates/cgp-component/src/namespaces.rs | 4 ++++ crates/cgp-error/Cargo.toml | 5 +---- .../cgp-macro-core/src/types/{ => generics}/impl_generics.rs | 0 crates/cgp-macro-core/src/types/generics/mod.rs | 5 +++++ .../src/types/generics}/type_generics.rs | 0 crates/cgp-macro-core/src/types/mod.rs | 4 ++-- .../cgp-macro-lib/src/derive_component/use_context_impl.rs | 2 +- crates/cgp-macro-lib/src/entrypoints/cgp_inherit.rs | 3 ++- crates/cgp-macro-lib/src/entrypoints/delegate_components.rs | 3 ++- crates/cgp-macro-lib/src/parse/delegate_components.rs | 4 ++-- crates/cgp-macro-lib/src/parse/is_provider_params.rs | 3 +-- crates/cgp-macro-lib/src/parse/mod.rs | 2 -- 13 files changed, 21 insertions(+), 16 deletions(-) rename crates/cgp-macro-core/src/types/{ => generics}/impl_generics.rs (100%) create mode 100644 crates/cgp-macro-core/src/types/generics/mod.rs rename crates/{cgp-macro-lib/src/parse => cgp-macro-core/src/types/generics}/type_generics.rs (100%) diff --git a/crates/cgp-component/src/lib.rs b/crates/cgp-component/src/lib.rs index cf9b41f5..c5d52c0f 100644 --- a/crates/cgp-component/src/lib.rs +++ b/crates/cgp-component/src/lib.rs @@ -11,7 +11,7 @@ mod namespaces; mod providers; mod traits; -pub use namespaces::DefaultNamespace; +pub use namespaces::{DefaultNamespace, DefaultNamespace1}; pub use providers::{ RedirectLookup, UseContext, UseDefault, UseDelegate, UseFields, WithContext, WithProvider, }; diff --git a/crates/cgp-component/src/namespaces.rs b/crates/cgp-component/src/namespaces.rs index 3c8e4bf5..73f21b99 100644 --- a/crates/cgp-component/src/namespaces.rs +++ b/crates/cgp-component/src/namespaces.rs @@ -1,3 +1,7 @@ pub trait DefaultNamespace { type Provider; } + +pub trait DefaultNamespace1 { + type Provider; +} diff --git a/crates/cgp-error/Cargo.toml b/crates/cgp-error/Cargo.toml index d1f29476..53f0432b 100644 --- a/crates/cgp-error/Cargo.toml +++ b/crates/cgp-error/Cargo.toml @@ -7,12 +7,9 @@ repository = { workspace = true } authors = { workspace = true } rust-version = { workspace = true } keywords = { workspace = true } -description = """ - Context-generic programming error components -""" [dependencies] -cgp = { version = "0.7.0", path = "../cgp-base", package = "cgp-base" } +cgp = { version = "0.7.0", path = "../cgp-base", package = "cgp-base" } cgp-macro = { workspace = true } cgp-type = { workspace = true } cgp-field = { workspace = true } diff --git a/crates/cgp-macro-core/src/types/impl_generics.rs b/crates/cgp-macro-core/src/types/generics/impl_generics.rs similarity index 100% rename from crates/cgp-macro-core/src/types/impl_generics.rs rename to crates/cgp-macro-core/src/types/generics/impl_generics.rs diff --git a/crates/cgp-macro-core/src/types/generics/mod.rs b/crates/cgp-macro-core/src/types/generics/mod.rs new file mode 100644 index 00000000..9d6eafc8 --- /dev/null +++ b/crates/cgp-macro-core/src/types/generics/mod.rs @@ -0,0 +1,5 @@ +mod impl_generics; +mod type_generics; + +pub use impl_generics::*; +pub use type_generics::*; diff --git a/crates/cgp-macro-lib/src/parse/type_generics.rs b/crates/cgp-macro-core/src/types/generics/type_generics.rs similarity index 100% rename from crates/cgp-macro-lib/src/parse/type_generics.rs rename to crates/cgp-macro-core/src/types/generics/type_generics.rs diff --git a/crates/cgp-macro-core/src/types/mod.rs b/crates/cgp-macro-core/src/types/mod.rs index 147b054d..d7c6fb11 100644 --- a/crates/cgp-macro-core/src/types/mod.rs +++ b/crates/cgp-macro-core/src/types/mod.rs @@ -1,7 +1,7 @@ -mod impl_generics; +mod generics; mod path; mod symbol; -pub use impl_generics::*; +pub use generics::*; pub use path::*; pub use symbol::*; diff --git a/crates/cgp-macro-lib/src/derive_component/use_context_impl.rs b/crates/cgp-macro-lib/src/derive_component/use_context_impl.rs index ffbc63d4..71294052 100644 --- a/crates/cgp-macro-lib/src/derive_component/use_context_impl.rs +++ b/crates/cgp-macro-lib/src/derive_component/use_context_impl.rs @@ -1,3 +1,4 @@ +use cgp_macro_core::types::TypeGenerics; use proc_macro2::Span; use quote::quote; use syn::spanned::Spanned; @@ -8,7 +9,6 @@ use syn::{ use crate::derive_component::delegate_fn::derive_delegated_fn_impl; use crate::derive_component::delegate_type::derive_delegate_type_impl; -use crate::parse::TypeGenerics; pub fn derive_use_context_impl( context_type: &Ident, diff --git a/crates/cgp-macro-lib/src/entrypoints/cgp_inherit.rs b/crates/cgp-macro-lib/src/entrypoints/cgp_inherit.rs index b5da921a..fab518cb 100644 --- a/crates/cgp-macro-lib/src/entrypoints/cgp_inherit.rs +++ b/crates/cgp-macro-lib/src/entrypoints/cgp_inherit.rs @@ -1,8 +1,9 @@ +use cgp_macro_core::types::TypeGenerics; use proc_macro2::TokenStream; use quote::quote; use syn::{Ident, ItemImpl, ItemStruct, parse_quote, parse2}; -use crate::parse::{SimpleType, TypeGenerics}; +use crate::parse::SimpleType; pub fn cgp_inherit(attr: TokenStream, body: TokenStream) -> syn::Result { let context_struct: ItemStruct = parse2(body)?; diff --git a/crates/cgp-macro-lib/src/entrypoints/delegate_components.rs b/crates/cgp-macro-lib/src/entrypoints/delegate_components.rs index 5dea004f..041efccd 100644 --- a/crates/cgp-macro-lib/src/entrypoints/delegate_components.rs +++ b/crates/cgp-macro-lib/src/entrypoints/delegate_components.rs @@ -1,9 +1,10 @@ +use cgp_macro_core::types::TypeGenerics; use proc_macro2::TokenStream; use quote::ToTokens; use syn::parse2; use crate::delegate_components::{define_struct, impl_delegate_components}; -use crate::parse::{DelegateComponents, SimpleType, TypeGenerics}; +use crate::parse::{DelegateComponents, SimpleType}; pub fn delegate_components(body: TokenStream) -> syn::Result { let spec: DelegateComponents = parse2(body)?; diff --git a/crates/cgp-macro-lib/src/parse/delegate_components.rs b/crates/cgp-macro-lib/src/parse/delegate_components.rs index 4dc5d010..399982a7 100644 --- a/crates/cgp-macro-lib/src/parse/delegate_components.rs +++ b/crates/cgp-macro-lib/src/parse/delegate_components.rs @@ -1,6 +1,6 @@ use core::iter; -use cgp_macro_core::types::ImplGenerics; +use cgp_macro_core::types::{ImplGenerics, TypeGenerics}; use proc_macro2::{Span, TokenStream}; use quote::{ToTokens, TokenStreamExt, quote}; use syn::parse::discouraged::Speculative; @@ -10,7 +10,7 @@ use syn::token::{At, Bracket, Colon, Comma, Gt, Lt, RArrow, Semi}; use syn::{Error, Generics, Ident, Token, Type, braced, bracketed, parse_quote, parse2}; use crate::delegate_components::merge_generics; -use crate::parse::{ComponentPaths, SimpleType, TypeGenerics}; +use crate::parse::{ComponentPaths, SimpleType}; pub struct DelegateComponents { pub new_struct: bool, diff --git a/crates/cgp-macro-lib/src/parse/is_provider_params.rs b/crates/cgp-macro-lib/src/parse/is_provider_params.rs index 8fbeb98e..37eca0c0 100644 --- a/crates/cgp-macro-lib/src/parse/is_provider_params.rs +++ b/crates/cgp-macro-lib/src/parse/is_provider_params.rs @@ -1,9 +1,8 @@ +use cgp_macro_core::types::TypeGenerics; use syn::punctuated::Punctuated; use syn::token::Comma; use syn::{GenericParam, Generics, Type, parse_quote}; -use crate::parse::TypeGenerics; - pub fn parse_is_provider_params(generics: &Generics) -> syn::Result> { let params = TypeGenerics::try_from(generics)?.generics.params; diff --git a/crates/cgp-macro-lib/src/parse/mod.rs b/crates/cgp-macro-lib/src/parse/mod.rs index 20ebbf99..6dd0a2a2 100644 --- a/crates/cgp-macro-lib/src/parse/mod.rs +++ b/crates/cgp-macro-lib/src/parse/mod.rs @@ -7,7 +7,6 @@ mod entry; mod is_provider_params; mod path; mod simple_type; -mod type_generics; mod type_spec; pub use check_components::*; @@ -19,5 +18,4 @@ pub use entry::*; pub use is_provider_params::*; pub use path::*; pub use simple_type::*; -pub use type_generics::*; pub use type_spec::*; From 992263dbf5073e97712d644a44fa492d212923a5 Mon Sep 17 00:00:00 2001 From: Soares Chen Date: Wed, 20 May 2026 22:38:20 +0200 Subject: [PATCH 24/81] Add NamespaceIdent --- .../src/types/generics/type_generics.rs | 10 ++++++++++ crates/cgp-macro-core/src/types/mod.rs | 2 ++ .../src/types/namespace/ident.rs | 18 ++++++++++++++++++ .../cgp-macro-core/src/types/namespace/mod.rs | 3 +++ 4 files changed, 33 insertions(+) create mode 100644 crates/cgp-macro-core/src/types/namespace/ident.rs create mode 100644 crates/cgp-macro-core/src/types/namespace/mod.rs diff --git a/crates/cgp-macro-core/src/types/generics/type_generics.rs b/crates/cgp-macro-core/src/types/generics/type_generics.rs index c4620438..e2a897dc 100644 --- a/crates/cgp-macro-core/src/types/generics/type_generics.rs +++ b/crates/cgp-macro-core/src/types/generics/type_generics.rs @@ -1,3 +1,5 @@ +use core::ops::Deref; + use proc_macro2::TokenStream; use quote::ToTokens; use syn::parse::{Parse, ParseStream}; @@ -8,6 +10,14 @@ pub struct TypeGenerics { pub generics: Generics, } +impl Deref for TypeGenerics { + type Target = Generics; + + fn deref(&self) -> &Generics { + &self.generics + } +} + impl Parse for TypeGenerics { fn parse(input: ParseStream) -> syn::Result { let generics: Generics = input.parse()?; diff --git a/crates/cgp-macro-core/src/types/mod.rs b/crates/cgp-macro-core/src/types/mod.rs index d7c6fb11..07f67a12 100644 --- a/crates/cgp-macro-core/src/types/mod.rs +++ b/crates/cgp-macro-core/src/types/mod.rs @@ -1,7 +1,9 @@ mod generics; mod path; mod symbol; +mod namespace; +pub use namespace::*; pub use generics::*; pub use path::*; pub use symbol::*; diff --git a/crates/cgp-macro-core/src/types/namespace/ident.rs b/crates/cgp-macro-core/src/types/namespace/ident.rs new file mode 100644 index 00000000..2249b60c --- /dev/null +++ b/crates/cgp-macro-core/src/types/namespace/ident.rs @@ -0,0 +1,18 @@ +use syn::Ident; +use syn::parse::{Parse, ParseStream}; + +use crate::types::TypeGenerics; + +pub struct NamespaceIdent { + pub ident: Ident, + pub generics: TypeGenerics, +} + +impl Parse for NamespaceIdent { + fn parse(input: ParseStream) -> syn::Result { + let ident = input.parse()?; + let generics = input.parse()?; + + Ok(Self { ident, generics }) + } +} diff --git a/crates/cgp-macro-core/src/types/namespace/mod.rs b/crates/cgp-macro-core/src/types/namespace/mod.rs new file mode 100644 index 00000000..d7d9dc2f --- /dev/null +++ b/crates/cgp-macro-core/src/types/namespace/mod.rs @@ -0,0 +1,3 @@ +mod ident; + +pub use ident::*; From 4affe2e67d012dbea70d322b71421d5146e84832 Mon Sep 17 00:00:00 2001 From: Soares Chen Date: Wed, 20 May 2026 22:58:58 +0200 Subject: [PATCH 25/81] Experiment on generic defaults --- crates/cgp-macro-core/src/types/mod.rs | 4 +-- crates/cgp-tests/src/namespaces/generics.rs | 22 ++++++++++++ crates/cgp-tests/src/namespaces/mod.rs | 5 ++- .../namespace_macro/default_generics.rs | 34 +++++++++++++++++++ .../namespace_macro/extended_namespace.rs | 2 +- .../namespace_tests/namespace_macro/mod.rs | 1 + 6 files changed, 62 insertions(+), 6 deletions(-) create mode 100644 crates/cgp-tests/src/namespaces/generics.rs create mode 100644 crates/cgp-tests/tests/namespace_tests/namespace_macro/default_generics.rs diff --git a/crates/cgp-macro-core/src/types/mod.rs b/crates/cgp-macro-core/src/types/mod.rs index 07f67a12..26a3cc8d 100644 --- a/crates/cgp-macro-core/src/types/mod.rs +++ b/crates/cgp-macro-core/src/types/mod.rs @@ -1,9 +1,9 @@ mod generics; +mod namespace; mod path; mod symbol; -mod namespace; -pub use namespace::*; pub use generics::*; +pub use namespace::*; pub use path::*; pub use symbol::*; diff --git a/crates/cgp-tests/src/namespaces/generics.rs b/crates/cgp-tests/src/namespaces/generics.rs new file mode 100644 index 00000000..35550e05 --- /dev/null +++ b/crates/cgp-tests/src/namespaces/generics.rs @@ -0,0 +1,22 @@ +use core::fmt::Display; + +use cgp::core::component::DefaultNamespace1; +use cgp::prelude::*; + +#[cgp_component(ShowImpl)] +#[prefix(@test)] +pub trait Show { + fn show(&self, value: &T) -> String; +} + +#[cgp_impl(new ShowWithDisplay)] +// #[default_impl(DefaultNamespace1)] +impl ShowImpl { + fn show(&self, value: &T) -> String { + value.to_string() + } +} + +impl DefaultNamespace1 for String { + type Provider = ShowWithDisplay; +} diff --git a/crates/cgp-tests/src/namespaces/mod.rs b/crates/cgp-tests/src/namespaces/mod.rs index 34d3c6b8..b9a1bced 100644 --- a/crates/cgp-tests/src/namespaces/mod.rs +++ b/crates/cgp-tests/src/namespaces/mod.rs @@ -1,3 +1,2 @@ -mod extended; - -pub use extended::*; +pub mod extended; +pub mod generics; diff --git a/crates/cgp-tests/tests/namespace_tests/namespace_macro/default_generics.rs b/crates/cgp-tests/tests/namespace_tests/namespace_macro/default_generics.rs new file mode 100644 index 00000000..b23f5c68 --- /dev/null +++ b/crates/cgp-tests/tests/namespace_tests/namespace_macro/default_generics.rs @@ -0,0 +1,34 @@ +use cgp::core::component::DefaultNamespace1; +use cgp::prelude::*; +use cgp_tests::namespaces::generics::{ShowImplComponent, ShowWithDisplay}; + +pub struct App; + +delegate_components! { + App { + namespace default; + + @test.ShowImplComponent.u64: + ShowWithDisplay, + + // namespace DefaultNamespace1 => @test.ShowImplComponent; + } +} + +impl + DelegateComponent>>> + for App +where + T: DefaultNamespace1, +{ + type Delegate = T::Provider; +} + +check_components! { + App { + ShowImplComponent: [ + String, + u64, + ] + } +} diff --git a/crates/cgp-tests/tests/namespace_tests/namespace_macro/extended_namespace.rs b/crates/cgp-tests/tests/namespace_tests/namespace_macro/extended_namespace.rs index 7e10c72f..64d08afb 100644 --- a/crates/cgp-tests/tests/namespace_tests/namespace_macro/extended_namespace.rs +++ b/crates/cgp-tests/tests/namespace_tests/namespace_macro/extended_namespace.rs @@ -2,7 +2,7 @@ use cgp::core::error::{ErrorRaiserComponent, ErrorTypeProviderComponent, ErrorWr use cgp::extra::error::RaiseFrom; use cgp::extra::handler::CanTryCompute; use cgp::prelude::*; -use cgp_tests::namespaces::ExtendedNamespace; +use cgp_tests::namespaces::extended::ExtendedNamespace; pub struct App; diff --git a/crates/cgp-tests/tests/namespace_tests/namespace_macro/mod.rs b/crates/cgp-tests/tests/namespace_tests/namespace_macro/mod.rs index dbd2d282..26d24110 100644 --- a/crates/cgp-tests/tests/namespace_tests/namespace_macro/mod.rs +++ b/crates/cgp-tests/tests/namespace_tests/namespace_macro/mod.rs @@ -1,4 +1,5 @@ pub mod basic; +pub mod default_generics; pub mod extended_namespace; pub mod multi_namespace; pub mod symbol_path; From f09cb68dc2a1608fb3f6c6e378f6a96a0bd22703 Mon Sep 17 00:00:00 2001 From: Soares Chen Date: Wed, 20 May 2026 23:14:41 +0200 Subject: [PATCH 26/81] Fully qualify type paths --- .../src/types/delegate_component/mod.rs | 1 + .../delegate_component/value_with_sub_entries.rs | 0 crates/cgp-macro-core/src/types/mod.rs | 12 +++++------- .../cgp-macro-core/src/types/namespace/ident.rs | 2 +- .../cgp-macro-core/src/types/path/path_head.rs | 3 ++- .../src/types/path/path_head_or_type.rs | 3 ++- crates/cgp-macro-core/src/types/path/unipath.rs | 3 +-- crates/cgp-macro-lib/src/attributes/namespace.rs | 2 +- crates/cgp-macro-lib/src/cgp_namespace/derive.rs | 2 +- crates/cgp-macro-lib/src/cgp_namespace/spec.rs | 2 +- .../src/delegate_components/impl_delegate.rs | 2 +- .../src/derive_component/use_context_impl.rs | 2 +- .../cgp-macro-lib/src/entrypoints/cgp_inherit.rs | 2 +- .../cgp-macro-lib/src/entrypoints/cgp_preset.rs | 2 +- .../entrypoints/delegate_and_check_components.rs | 2 +- .../src/entrypoints/delegate_components.rs | 2 +- .../cgp-macro-lib/src/parse/check_components.rs | 2 +- .../src/parse/delegate_and_check_components.rs | 2 +- .../src/parse/delegate_components.rs | 2 +- .../src/parse/is_provider_params.rs | 2 +- crates/cgp-macro-lib/src/parse/path.rs | 3 ++- crates/cgp-macro-lib/src/parse/type_spec.rs | 2 +- .../cgp-macro-lib/src/preset/impl_is_preset.rs | 2 +- crates/cgp-tests/src/namespaces/generics.rs | 16 ++++++++++++++++ 24 files changed, 45 insertions(+), 28 deletions(-) create mode 100644 crates/cgp-macro-core/src/types/delegate_component/mod.rs create mode 100644 crates/cgp-macro-core/src/types/delegate_component/value_with_sub_entries.rs diff --git a/crates/cgp-macro-core/src/types/delegate_component/mod.rs b/crates/cgp-macro-core/src/types/delegate_component/mod.rs new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/crates/cgp-macro-core/src/types/delegate_component/mod.rs @@ -0,0 +1 @@ + diff --git a/crates/cgp-macro-core/src/types/delegate_component/value_with_sub_entries.rs b/crates/cgp-macro-core/src/types/delegate_component/value_with_sub_entries.rs new file mode 100644 index 00000000..e69de29b diff --git a/crates/cgp-macro-core/src/types/mod.rs b/crates/cgp-macro-core/src/types/mod.rs index 26a3cc8d..515c0695 100644 --- a/crates/cgp-macro-core/src/types/mod.rs +++ b/crates/cgp-macro-core/src/types/mod.rs @@ -1,9 +1,7 @@ -mod generics; -mod namespace; -mod path; -mod symbol; +pub mod delegate_component; +pub mod generics; +pub mod namespace; +pub mod path; +pub mod symbol; -pub use generics::*; -pub use namespace::*; -pub use path::*; pub use symbol::*; diff --git a/crates/cgp-macro-core/src/types/namespace/ident.rs b/crates/cgp-macro-core/src/types/namespace/ident.rs index 2249b60c..2aa80364 100644 --- a/crates/cgp-macro-core/src/types/namespace/ident.rs +++ b/crates/cgp-macro-core/src/types/namespace/ident.rs @@ -1,7 +1,7 @@ use syn::Ident; use syn::parse::{Parse, ParseStream}; -use crate::types::TypeGenerics; +use crate::types::generics::TypeGenerics; pub struct NamespaceIdent { pub ident: Ident, diff --git a/crates/cgp-macro-core/src/types/path/path_head.rs b/crates/cgp-macro-core/src/types/path/path_head.rs index a9dccea8..a0ce9ea6 100644 --- a/crates/cgp-macro-core/src/types/path/path_head.rs +++ b/crates/cgp-macro-core/src/types/path/path_head.rs @@ -3,7 +3,8 @@ use syn::parse::{Parse, ParseStream}; use syn::punctuated::Punctuated; use syn::token::{Brace, Comma, Dot}; -use crate::types::{ImplGenerics, PathElement, UniPath}; +use crate::types::generics::ImplGenerics; +use crate::types::path::{PathElement, UniPath}; #[derive(Debug, Clone)] pub enum PathHead { diff --git a/crates/cgp-macro-core/src/types/path/path_head_or_type.rs b/crates/cgp-macro-core/src/types/path/path_head_or_type.rs index 1292272d..41cffc45 100644 --- a/crates/cgp-macro-core/src/types/path/path_head_or_type.rs +++ b/crates/cgp-macro-core/src/types/path/path_head_or_type.rs @@ -2,7 +2,8 @@ use syn::Type; use syn::parse::{Parse, ParseStream}; use syn::token::At; -use crate::types::{ImplGenerics, PathHead}; +use crate::types::generics::ImplGenerics; +use crate::types::path::PathHead; #[derive(Debug, Clone)] pub enum PathHeadOrType { diff --git a/crates/cgp-macro-core/src/types/path/unipath.rs b/crates/cgp-macro-core/src/types/path/unipath.rs index 3507c95d..e1d2d35a 100644 --- a/crates/cgp-macro-core/src/types/path/unipath.rs +++ b/crates/cgp-macro-core/src/types/path/unipath.rs @@ -6,8 +6,7 @@ use syn::punctuated::Punctuated; use syn::token::{At, Dot}; use crate::exports::{Nil, PathCons}; -use crate::types::PrefixPath; -use crate::types::path::PathElement; +use crate::types::path::{PathElement, PrefixPath}; #[derive(Debug, Clone, Default)] pub struct UniPath { diff --git a/crates/cgp-macro-lib/src/attributes/namespace.rs b/crates/cgp-macro-lib/src/attributes/namespace.rs index 1182a8bb..31aa51e0 100644 --- a/crates/cgp-macro-lib/src/attributes/namespace.rs +++ b/crates/cgp-macro-lib/src/attributes/namespace.rs @@ -1,4 +1,4 @@ -use cgp_macro_core::types::UniPath; +use cgp_macro_core::types::path::UniPath; use syn::Ident; use syn::parse::{Parse, ParseStream}; use syn::token::In; diff --git a/crates/cgp-macro-lib/src/cgp_namespace/derive.rs b/crates/cgp-macro-lib/src/cgp_namespace/derive.rs index efa0413f..1f56895b 100644 --- a/crates/cgp-macro-lib/src/cgp_namespace/derive.rs +++ b/crates/cgp-macro-lib/src/cgp_namespace/derive.rs @@ -1,4 +1,4 @@ -use cgp_macro_core::types::PathHeadOrType; +use cgp_macro_core::types::path::PathHeadOrType; use proc_macro2::TokenStream; use quote::quote; use syn::{Ident, ItemImpl, ItemStruct, ItemTrait, parse_quote, parse2}; diff --git a/crates/cgp-macro-lib/src/cgp_namespace/spec.rs b/crates/cgp-macro-lib/src/cgp_namespace/spec.rs index 62450912..89152c05 100644 --- a/crates/cgp-macro-lib/src/cgp_namespace/spec.rs +++ b/crates/cgp-macro-lib/src/cgp_namespace/spec.rs @@ -1,4 +1,4 @@ -use cgp_macro_core::types::{PathHeadOrType, UniPath}; +use cgp_macro_core::types::path::{PathHeadOrType, UniPath}; use syn::parse::{Parse, ParseStream}; use syn::punctuated::Punctuated; use syn::token::{Colon, Comma}; diff --git a/crates/cgp-macro-lib/src/delegate_components/impl_delegate.rs b/crates/cgp-macro-lib/src/delegate_components/impl_delegate.rs index 312af732..1402c97b 100644 --- a/crates/cgp-macro-lib/src/delegate_components/impl_delegate.rs +++ b/crates/cgp-macro-lib/src/delegate_components/impl_delegate.rs @@ -2,7 +2,7 @@ use alloc::boxed::Box; use alloc::vec; use alloc::vec::Vec; -use cgp_macro_core::types::ImplGenerics; +use cgp_macro_core::types::generics::ImplGenerics; use proc_macro2::TokenStream; use quote::{ToTokens, quote}; use syn::punctuated::Punctuated; diff --git a/crates/cgp-macro-lib/src/derive_component/use_context_impl.rs b/crates/cgp-macro-lib/src/derive_component/use_context_impl.rs index 71294052..918a1e6a 100644 --- a/crates/cgp-macro-lib/src/derive_component/use_context_impl.rs +++ b/crates/cgp-macro-lib/src/derive_component/use_context_impl.rs @@ -1,4 +1,4 @@ -use cgp_macro_core::types::TypeGenerics; +use cgp_macro_core::types::generics::TypeGenerics; use proc_macro2::Span; use quote::quote; use syn::spanned::Spanned; diff --git a/crates/cgp-macro-lib/src/entrypoints/cgp_inherit.rs b/crates/cgp-macro-lib/src/entrypoints/cgp_inherit.rs index fab518cb..42745075 100644 --- a/crates/cgp-macro-lib/src/entrypoints/cgp_inherit.rs +++ b/crates/cgp-macro-lib/src/entrypoints/cgp_inherit.rs @@ -1,4 +1,4 @@ -use cgp_macro_core::types::TypeGenerics; +use cgp_macro_core::types::generics::TypeGenerics; use proc_macro2::TokenStream; use quote::quote; use syn::{Ident, ItemImpl, ItemStruct, parse_quote, parse2}; diff --git a/crates/cgp-macro-lib/src/entrypoints/cgp_preset.rs b/crates/cgp-macro-lib/src/entrypoints/cgp_preset.rs index ba0d8ac6..4d2977ec 100644 --- a/crates/cgp-macro-lib/src/entrypoints/cgp_preset.rs +++ b/crates/cgp-macro-lib/src/entrypoints/cgp_preset.rs @@ -1,6 +1,6 @@ use std::collections::HashSet; -use cgp_macro_core::types::ImplGenerics; +use cgp_macro_core::types::generics::ImplGenerics; use proc_macro2::{Span, TokenStream}; use quote::{ToTokens, TokenStreamExt, quote}; use syn::punctuated::Punctuated; diff --git a/crates/cgp-macro-lib/src/entrypoints/delegate_and_check_components.rs b/crates/cgp-macro-lib/src/entrypoints/delegate_and_check_components.rs index 986a17b3..4763b9f9 100644 --- a/crates/cgp-macro-lib/src/entrypoints/delegate_and_check_components.rs +++ b/crates/cgp-macro-lib/src/entrypoints/delegate_and_check_components.rs @@ -1,4 +1,4 @@ -use cgp_macro_core::types::ImplGenerics; +use cgp_macro_core::types::generics::ImplGenerics; use proc_macro2::{Span, TokenStream}; use quote::{ToTokens, TokenStreamExt}; use syn::punctuated::Punctuated; diff --git a/crates/cgp-macro-lib/src/entrypoints/delegate_components.rs b/crates/cgp-macro-lib/src/entrypoints/delegate_components.rs index 041efccd..1a8dde64 100644 --- a/crates/cgp-macro-lib/src/entrypoints/delegate_components.rs +++ b/crates/cgp-macro-lib/src/entrypoints/delegate_components.rs @@ -1,4 +1,4 @@ -use cgp_macro_core::types::TypeGenerics; +use cgp_macro_core::types::generics::TypeGenerics; use proc_macro2::TokenStream; use quote::ToTokens; use syn::parse2; diff --git a/crates/cgp-macro-lib/src/parse/check_components.rs b/crates/cgp-macro-lib/src/parse/check_components.rs index cc85bad0..00bca26b 100644 --- a/crates/cgp-macro-lib/src/parse/check_components.rs +++ b/crates/cgp-macro-lib/src/parse/check_components.rs @@ -1,4 +1,4 @@ -use cgp_macro_core::types::ImplGenerics; +use cgp_macro_core::types::generics::ImplGenerics; use proc_macro2::Span; use quote::ToTokens; use syn::parse::{Parse, ParseStream}; diff --git a/crates/cgp-macro-lib/src/parse/delegate_and_check_components.rs b/crates/cgp-macro-lib/src/parse/delegate_and_check_components.rs index 2d07ef7f..ba8e96eb 100644 --- a/crates/cgp-macro-lib/src/parse/delegate_and_check_components.rs +++ b/crates/cgp-macro-lib/src/parse/delegate_and_check_components.rs @@ -1,6 +1,6 @@ use core::iter; -use cgp_macro_core::types::ImplGenerics; +use cgp_macro_core::types::generics::ImplGenerics; use quote::ToTokens; use syn::parse::{Parse, ParseStream}; use syn::punctuated::Punctuated; diff --git a/crates/cgp-macro-lib/src/parse/delegate_components.rs b/crates/cgp-macro-lib/src/parse/delegate_components.rs index 399982a7..1c0197a3 100644 --- a/crates/cgp-macro-lib/src/parse/delegate_components.rs +++ b/crates/cgp-macro-lib/src/parse/delegate_components.rs @@ -1,6 +1,6 @@ use core::iter; -use cgp_macro_core::types::{ImplGenerics, TypeGenerics}; +use cgp_macro_core::types::generics::{ImplGenerics, TypeGenerics}; use proc_macro2::{Span, TokenStream}; use quote::{ToTokens, TokenStreamExt, quote}; use syn::parse::discouraged::Speculative; diff --git a/crates/cgp-macro-lib/src/parse/is_provider_params.rs b/crates/cgp-macro-lib/src/parse/is_provider_params.rs index 37eca0c0..88c085fd 100644 --- a/crates/cgp-macro-lib/src/parse/is_provider_params.rs +++ b/crates/cgp-macro-lib/src/parse/is_provider_params.rs @@ -1,4 +1,4 @@ -use cgp_macro_core::types::TypeGenerics; +use cgp_macro_core::types::generics::TypeGenerics; use syn::punctuated::Punctuated; use syn::token::Comma; use syn::{GenericParam, Generics, Type, parse_quote}; diff --git a/crates/cgp-macro-lib/src/parse/path.rs b/crates/cgp-macro-lib/src/parse/path.rs index 72b1894a..8353350c 100644 --- a/crates/cgp-macro-lib/src/parse/path.rs +++ b/crates/cgp-macro-lib/src/parse/path.rs @@ -1,4 +1,5 @@ -use cgp_macro_core::types::{ImplGenerics, PathHead}; +use cgp_macro_core::types::generics::ImplGenerics; +use cgp_macro_core::types::path::PathHead; use proc_macro2::TokenStream; use quote::{ToTokens, quote}; use syn::parse::{Parse, ParseStream}; diff --git a/crates/cgp-macro-lib/src/parse/type_spec.rs b/crates/cgp-macro-lib/src/parse/type_spec.rs index 1cd40b95..285a96a9 100644 --- a/crates/cgp-macro-lib/src/parse/type_spec.rs +++ b/crates/cgp-macro-lib/src/parse/type_spec.rs @@ -1,4 +1,4 @@ -use cgp_macro_core::types::ImplGenerics; +use cgp_macro_core::types::generics::ImplGenerics; use quote::ToTokens; use syn::Ident; use syn::parse::{Parse, ParseStream}; diff --git a/crates/cgp-macro-lib/src/preset/impl_is_preset.rs b/crates/cgp-macro-lib/src/preset/impl_is_preset.rs index 3daa0632..ec912b26 100644 --- a/crates/cgp-macro-lib/src/preset/impl_is_preset.rs +++ b/crates/cgp-macro-lib/src/preset/impl_is_preset.rs @@ -1,6 +1,6 @@ use alloc::vec::Vec; -use cgp_macro_core::types::ImplGenerics; +use cgp_macro_core::types::generics::ImplGenerics; use syn::punctuated::Punctuated; use syn::token::Comma; use syn::{Ident, ItemImpl, Type, parse_quote}; diff --git a/crates/cgp-tests/src/namespaces/generics.rs b/crates/cgp-tests/src/namespaces/generics.rs index 35550e05..375288d1 100644 --- a/crates/cgp-tests/src/namespaces/generics.rs +++ b/crates/cgp-tests/src/namespaces/generics.rs @@ -17,6 +17,22 @@ impl ShowImpl { } } +// cgp_namespace! { +// DefaultShow { +// T: +// @ShowWithDisplay, +// } +// } + +/* + cgp_namespace! { + DefaultNamespace1 { + String: + ShowWithDisplay, + } + } +*/ + impl DefaultNamespace1 for String { type Provider = ShowWithDisplay; } From 0cc23ab8000ed69ff405fb66a37d4969fa009e50 Mon Sep 17 00:00:00 2001 From: Soares Chen Date: Wed, 20 May 2026 23:41:56 +0200 Subject: [PATCH 27/81] Reimplementing DelegateEntry --- .../src/types/delegate_component/entry.rs | 51 ++++++++++++++ .../src/types/delegate_component/key.rs | 51 ++++++++++++++ .../src/types/delegate_component/mod.rs | 6 ++ .../src/types/delegate_component/value.rs | 68 +++++++++++++++++++ .../value_with_sub_entries.rs | 0 .../src/parse/delegate_components.rs | 1 - 6 files changed, 176 insertions(+), 1 deletion(-) create mode 100644 crates/cgp-macro-core/src/types/delegate_component/entry.rs create mode 100644 crates/cgp-macro-core/src/types/delegate_component/key.rs create mode 100644 crates/cgp-macro-core/src/types/delegate_component/value.rs delete mode 100644 crates/cgp-macro-core/src/types/delegate_component/value_with_sub_entries.rs diff --git a/crates/cgp-macro-core/src/types/delegate_component/entry.rs b/crates/cgp-macro-core/src/types/delegate_component/entry.rs new file mode 100644 index 00000000..1bd79702 --- /dev/null +++ b/crates/cgp-macro-core/src/types/delegate_component/entry.rs @@ -0,0 +1,51 @@ +use syn::parse::{Parse, ParseStream}; +use syn::token::{Colon, RArrow}; + +use crate::types::delegate_component::{DelegateKey, DelegateValue}; + +pub enum DelegateEntry { + Normal(NormalDelegateEntry), + Direct(DirectDelegateEntry), +} + +pub struct NormalDelegateEntry { + pub key: DelegateKey, + pub colon: Colon, + pub value: DelegateValue, +} + +pub struct DirectDelegateEntry { + pub key: DelegateKey, + pub arrow: RArrow, + pub value: DelegateValue, +} + +pub enum DelegateMode { + Normal(Colon), + Direct(RArrow), +} + +impl Parse for DelegateEntry { + fn parse(input: ParseStream) -> syn::Result { + let key = input.parse()?; + let mode: DelegateMode = input.parse()?; + let value = input.parse()?; + + let entry = match mode { + DelegateMode::Normal(colon) => Self::Normal(NormalDelegateEntry { key, colon, value }), + DelegateMode::Direct(arrow) => Self::Direct(DirectDelegateEntry { key, arrow, value }), + }; + + Ok(entry) + } +} + +impl Parse for DelegateMode { + fn parse(input: ParseStream) -> syn::Result { + if input.peek(RArrow) { + Ok(Self::Direct(input.parse()?)) + } else { + Ok(Self::Normal(input.parse()?)) + } + } +} diff --git a/crates/cgp-macro-core/src/types/delegate_component/key.rs b/crates/cgp-macro-core/src/types/delegate_component/key.rs new file mode 100644 index 00000000..5ad74d4a --- /dev/null +++ b/crates/cgp-macro-core/src/types/delegate_component/key.rs @@ -0,0 +1,51 @@ +use syn::bracketed; +use syn::parse::{Parse, ParseStream}; +use syn::punctuated::Punctuated; +use syn::token::{Bracket, Comma, Type}; + +use crate::types::generics::ImplGenerics; + +pub enum DelegateKey { + Single(SingleDelegateKey), + Multi(MultiDelegateKey), +} + +pub struct SingleDelegateKey { + pub generics: ImplGenerics, + pub ty: Type, +} + +pub struct MultiDelegateKey { + pub keys: Punctuated, +} + +impl Parse for DelegateKey { + fn parse(input: ParseStream) -> syn::Result { + if input.peek(Bracket) { + let keys = input.parse()?; + Ok(Self::Multi(keys)) + } else { + let key = input.parse()?; + Ok(Self::Single(key)) + } + } +} + +impl Parse for SingleDelegateKey { + fn parse(input: ParseStream) -> syn::Result { + let generics = input.parse()?; + let ty = input.parse()?; + + Ok(Self { generics, ty }) + } +} + +impl Parse for MultiDelegateKey { + fn parse(input: ParseStream) -> syn::Result { + let body; + bracketed!(body in input); + let keys = Punctuated::parse_terminated(&body)?; + + Ok(Self { keys }) + } +} diff --git a/crates/cgp-macro-core/src/types/delegate_component/mod.rs b/crates/cgp-macro-core/src/types/delegate_component/mod.rs index 8b137891..bd3b5256 100644 --- a/crates/cgp-macro-core/src/types/delegate_component/mod.rs +++ b/crates/cgp-macro-core/src/types/delegate_component/mod.rs @@ -1 +1,7 @@ +mod entry; +mod key; +mod value; +pub use entry::*; +pub use key::*; +pub use value::*; diff --git a/crates/cgp-macro-core/src/types/delegate_component/value.rs b/crates/cgp-macro-core/src/types/delegate_component/value.rs new file mode 100644 index 00000000..07ad116f --- /dev/null +++ b/crates/cgp-macro-core/src/types/delegate_component/value.rs @@ -0,0 +1,68 @@ +use syn::parse::discouraged::Speculative; +use syn::parse::{Parse, ParseStream}; +use syn::punctuated::Punctuated; +use syn::token::{Comma, Gt, Lt}; +use syn::{Error, Generics, Ident, Type, braced}; + +use crate::types::delegate_component::DelegateEntry; +use crate::types::generics::TypeGenerics; + +pub enum DelegateValue { + Type(Type), + WithInner(DelegateValueWithInnerEntries), +} + +pub struct DelegateValueWithInnerEntries { + pub wrapper_ident: Ident, + pub struct_ident: Ident, + pub struct_generics: Generics, + pub entries: Punctuated, +} + +impl Parse for DelegateValue { + fn parse(input: ParseStream) -> syn::Result { + let fork = input.fork(); + + if let Ok(value) = fork.parse::() { + input.advance_to(&fork); + return Ok(Self::WithInner(value)); + } + + let ty: Type = input.parse()?; + Ok(Self::Type(ty)) + } +} + +impl Parse for DelegateValueWithInnerEntries { + fn parse(input: ParseStream) -> syn::Result { + let wrapper_ident = input.parse()?; + + let _: Lt = input.parse()?; + + let new_ident: Ident = input.parse()?; + + if new_ident != "new" { + return Err(Error::new(new_ident.span(), "expect `new` keyword")); + } + + let struct_ident = input.parse()?; + + let struct_generics: TypeGenerics = input.parse()?; + + let entries = { + let content; + braced!(content in input); + + Punctuated::parse_terminated(&content)? + }; + + let _: Gt = input.parse()?; + + Ok(Self { + wrapper_ident, + struct_ident, + struct_generics: struct_generics.generics, + entries, + }) + } +} diff --git a/crates/cgp-macro-core/src/types/delegate_component/value_with_sub_entries.rs b/crates/cgp-macro-core/src/types/delegate_component/value_with_sub_entries.rs deleted file mode 100644 index e69de29b..00000000 diff --git a/crates/cgp-macro-lib/src/parse/delegate_components.rs b/crates/cgp-macro-lib/src/parse/delegate_components.rs index 1c0197a3..455b8e52 100644 --- a/crates/cgp-macro-lib/src/parse/delegate_components.rs +++ b/crates/cgp-macro-lib/src/parse/delegate_components.rs @@ -38,7 +38,6 @@ pub enum DelegateValue { New(DelegateNewValue), } -#[allow(dead_code)] #[derive(Clone)] pub enum DelegateMode { Provider(Colon), From 6211b887a1e27b9c3b18db5a53e5bc46a1ec5154 Mon Sep 17 00:00:00 2001 From: Soares Chen Date: Wed, 20 May 2026 23:46:24 +0200 Subject: [PATCH 28/81] Add PathDelegateKey --- .../src/types/delegate_component/key.rs | 31 ++++++++++++++++--- 1 file changed, 26 insertions(+), 5 deletions(-) diff --git a/crates/cgp-macro-core/src/types/delegate_component/key.rs b/crates/cgp-macro-core/src/types/delegate_component/key.rs index 5ad74d4a..526fa1e7 100644 --- a/crates/cgp-macro-core/src/types/delegate_component/key.rs +++ b/crates/cgp-macro-core/src/types/delegate_component/key.rs @@ -1,13 +1,16 @@ use syn::bracketed; +use syn::parse::discouraged::Speculative; use syn::parse::{Parse, ParseStream}; use syn::punctuated::Punctuated; -use syn::token::{Bracket, Comma, Type}; +use syn::token::{At, Bracket, Comma, Type}; use crate::types::generics::ImplGenerics; +use crate::types::path::PathHead; pub enum DelegateKey { Single(SingleDelegateKey), Multi(MultiDelegateKey), + Path(PathDelegateKey), } pub struct SingleDelegateKey { @@ -19,15 +22,33 @@ pub struct MultiDelegateKey { pub keys: Punctuated, } +pub struct PathDelegateKey { + pub generics: ImplGenerics, + pub at: At, + pub path: PathHead, +} + impl Parse for DelegateKey { fn parse(input: ParseStream) -> syn::Result { - if input.peek(Bracket) { + let fork = input.fork(); + let generics: ImplGenerics = fork.parse()?; + + let key = if fork.peek(At) { + input.advance_to(&fork); + + let at = input.parse()?; + let path = input.parse()?; + + Self::Path(PathDelegateKey { generics, at, path }) + } else if input.peek(Bracket) { let keys = input.parse()?; - Ok(Self::Multi(keys)) + Self::Multi(keys) } else { let key = input.parse()?; - Ok(Self::Single(key)) - } + Self::Single(key) + }; + + Ok(key) } } From fc9fccdf9b5fff8bce9ad0c0ce4c3da813c467fc Mon Sep 17 00:00:00 2001 From: Soares Chen Date: Thu, 21 May 2026 22:07:36 +0200 Subject: [PATCH 29/81] Reorganize DelegateEntry constructs --- .../src/types/delegate_component/entry.rs | 51 ------------------- .../delegate_component/entry/combined.rs | 23 +++++++++ .../types/delegate_component/entry/direct.rs | 9 ++++ .../src/types/delegate_component/entry/mod.rs | 11 ++++ .../types/delegate_component/entry/mode.rs | 17 +++++++ .../types/delegate_component/entry/normal.rs | 9 ++++ .../types/delegate_component/entry/open.rs | 9 ++++ 7 files changed, 78 insertions(+), 51 deletions(-) delete mode 100644 crates/cgp-macro-core/src/types/delegate_component/entry.rs create mode 100644 crates/cgp-macro-core/src/types/delegate_component/entry/combined.rs create mode 100644 crates/cgp-macro-core/src/types/delegate_component/entry/direct.rs create mode 100644 crates/cgp-macro-core/src/types/delegate_component/entry/mod.rs create mode 100644 crates/cgp-macro-core/src/types/delegate_component/entry/mode.rs create mode 100644 crates/cgp-macro-core/src/types/delegate_component/entry/normal.rs create mode 100644 crates/cgp-macro-core/src/types/delegate_component/entry/open.rs diff --git a/crates/cgp-macro-core/src/types/delegate_component/entry.rs b/crates/cgp-macro-core/src/types/delegate_component/entry.rs deleted file mode 100644 index 1bd79702..00000000 --- a/crates/cgp-macro-core/src/types/delegate_component/entry.rs +++ /dev/null @@ -1,51 +0,0 @@ -use syn::parse::{Parse, ParseStream}; -use syn::token::{Colon, RArrow}; - -use crate::types::delegate_component::{DelegateKey, DelegateValue}; - -pub enum DelegateEntry { - Normal(NormalDelegateEntry), - Direct(DirectDelegateEntry), -} - -pub struct NormalDelegateEntry { - pub key: DelegateKey, - pub colon: Colon, - pub value: DelegateValue, -} - -pub struct DirectDelegateEntry { - pub key: DelegateKey, - pub arrow: RArrow, - pub value: DelegateValue, -} - -pub enum DelegateMode { - Normal(Colon), - Direct(RArrow), -} - -impl Parse for DelegateEntry { - fn parse(input: ParseStream) -> syn::Result { - let key = input.parse()?; - let mode: DelegateMode = input.parse()?; - let value = input.parse()?; - - let entry = match mode { - DelegateMode::Normal(colon) => Self::Normal(NormalDelegateEntry { key, colon, value }), - DelegateMode::Direct(arrow) => Self::Direct(DirectDelegateEntry { key, arrow, value }), - }; - - Ok(entry) - } -} - -impl Parse for DelegateMode { - fn parse(input: ParseStream) -> syn::Result { - if input.peek(RArrow) { - Ok(Self::Direct(input.parse()?)) - } else { - Ok(Self::Normal(input.parse()?)) - } - } -} diff --git a/crates/cgp-macro-core/src/types/delegate_component/entry/combined.rs b/crates/cgp-macro-core/src/types/delegate_component/entry/combined.rs new file mode 100644 index 00000000..8ecbb70e --- /dev/null +++ b/crates/cgp-macro-core/src/types/delegate_component/entry/combined.rs @@ -0,0 +1,23 @@ +use syn::parse::{Parse, ParseStream}; + +use crate::types::delegate_component::{DelegateMode, DirectDelegateEntry, NormalDelegateEntry}; + +pub enum DelegateEntry { + Normal(NormalDelegateEntry), + Direct(DirectDelegateEntry), +} + +impl Parse for DelegateEntry { + fn parse(input: ParseStream) -> syn::Result { + let key = input.parse()?; + let mode: DelegateMode = input.parse()?; + let value = input.parse()?; + + let entry = match mode { + DelegateMode::Normal(colon) => Self::Normal(NormalDelegateEntry { key, colon, value }), + DelegateMode::Direct(arrow) => Self::Direct(DirectDelegateEntry { key, arrow, value }), + }; + + Ok(entry) + } +} diff --git a/crates/cgp-macro-core/src/types/delegate_component/entry/direct.rs b/crates/cgp-macro-core/src/types/delegate_component/entry/direct.rs new file mode 100644 index 00000000..c41c9afd --- /dev/null +++ b/crates/cgp-macro-core/src/types/delegate_component/entry/direct.rs @@ -0,0 +1,9 @@ +use syn::token::RArrow; + +use crate::types::delegate_component::{DelegateKey, DelegateValue}; + +pub struct DirectDelegateEntry { + pub key: DelegateKey, + pub arrow: RArrow, + pub value: DelegateValue, +} diff --git a/crates/cgp-macro-core/src/types/delegate_component/entry/mod.rs b/crates/cgp-macro-core/src/types/delegate_component/entry/mod.rs new file mode 100644 index 00000000..7a7b2fc2 --- /dev/null +++ b/crates/cgp-macro-core/src/types/delegate_component/entry/mod.rs @@ -0,0 +1,11 @@ +mod combined; +mod direct; +mod mode; +mod normal; +mod open; + +pub use combined::*; +pub use direct::*; +pub use mode::*; +pub use normal::*; +pub use open::*; diff --git a/crates/cgp-macro-core/src/types/delegate_component/entry/mode.rs b/crates/cgp-macro-core/src/types/delegate_component/entry/mode.rs new file mode 100644 index 00000000..5fb21d48 --- /dev/null +++ b/crates/cgp-macro-core/src/types/delegate_component/entry/mode.rs @@ -0,0 +1,17 @@ +use syn::parse::{Parse, ParseStream}; +use syn::token::{Colon, RArrow}; + +pub enum DelegateMode { + Normal(Colon), + Direct(RArrow), +} + +impl Parse for DelegateMode { + fn parse(input: ParseStream) -> syn::Result { + if input.peek(RArrow) { + Ok(Self::Direct(input.parse()?)) + } else { + Ok(Self::Normal(input.parse()?)) + } + } +} diff --git a/crates/cgp-macro-core/src/types/delegate_component/entry/normal.rs b/crates/cgp-macro-core/src/types/delegate_component/entry/normal.rs new file mode 100644 index 00000000..5f4832e2 --- /dev/null +++ b/crates/cgp-macro-core/src/types/delegate_component/entry/normal.rs @@ -0,0 +1,9 @@ +use syn::token::Colon; + +use crate::types::delegate_component::{DelegateKey, DelegateValue}; + +pub struct NormalDelegateEntry { + pub key: DelegateKey, + pub colon: Colon, + pub value: DelegateValue, +} diff --git a/crates/cgp-macro-core/src/types/delegate_component/entry/open.rs b/crates/cgp-macro-core/src/types/delegate_component/entry/open.rs new file mode 100644 index 00000000..89d45a49 --- /dev/null +++ b/crates/cgp-macro-core/src/types/delegate_component/entry/open.rs @@ -0,0 +1,9 @@ +use syn::punctuated::Punctuated; +use syn::token::{Comma, Semi}; +use syn::{Ident, Type}; + +pub struct OpenDelegateEntry { + pub open: Ident, + pub components: Punctuated, + pub semi: Semi, +} From bdbd37b9792fcef339b8e955233c5f8e8fc98864 Mon Sep 17 00:00:00 2001 From: Soares Chen Date: Thu, 21 May 2026 22:19:35 +0200 Subject: [PATCH 30/81] Add keyword constructs --- crates/cgp-macro-core/src/macros.rs | 14 +++++++++ crates/cgp-macro-core/src/traits/keyword.rs | 3 ++ crates/cgp-macro-core/src/traits/mod.rs | 2 ++ .../types/delegate_component/entry/open.rs | 4 +++ crates/cgp-macro-core/src/types/keyword.rs | 30 +++++++++++++++++++ crates/cgp-macro-core/src/types/mod.rs | 3 +- 6 files changed, 54 insertions(+), 2 deletions(-) create mode 100644 crates/cgp-macro-core/src/traits/keyword.rs create mode 100644 crates/cgp-macro-core/src/types/keyword.rs diff --git a/crates/cgp-macro-core/src/macros.rs b/crates/cgp-macro-core/src/macros.rs index 02db7ff4..d0814484 100644 --- a/crates/cgp-macro-core/src/macros.rs +++ b/crates/cgp-macro-core/src/macros.rs @@ -20,3 +20,17 @@ macro_rules! export_constructs { $( $crate::export_construct! { $from $( => $to )* } )* }; } + +#[macro_export] +macro_rules! define_keyword { + ( $struct_ident:ident, $impl_ident:ident, $value:literal ) => { + pub struct $impl_ident; + + impl $crate::traits::IsKeyword for $impl_ident { + const IDENT: &'static str = "open"; + } + + pub type $struct_ident = $crate::types::keyword::Keyword<$impl_ident>; + + } +} diff --git a/crates/cgp-macro-core/src/traits/keyword.rs b/crates/cgp-macro-core/src/traits/keyword.rs new file mode 100644 index 00000000..c7e2e6a2 --- /dev/null +++ b/crates/cgp-macro-core/src/traits/keyword.rs @@ -0,0 +1,3 @@ +pub trait IsKeyword { + const IDENT: &'static str; +} diff --git a/crates/cgp-macro-core/src/traits/mod.rs b/crates/cgp-macro-core/src/traits/mod.rs index b15bcc24..9484894c 100644 --- a/crates/cgp-macro-core/src/traits/mod.rs +++ b/crates/cgp-macro-core/src/traits/mod.rs @@ -1,3 +1,5 @@ +mod keyword; mod to_type; +pub use keyword::*; pub use to_type::*; diff --git a/crates/cgp-macro-core/src/types/delegate_component/entry/open.rs b/crates/cgp-macro-core/src/types/delegate_component/entry/open.rs index 89d45a49..63acca12 100644 --- a/crates/cgp-macro-core/src/types/delegate_component/entry/open.rs +++ b/crates/cgp-macro-core/src/types/delegate_component/entry/open.rs @@ -2,6 +2,10 @@ use syn::punctuated::Punctuated; use syn::token::{Comma, Semi}; use syn::{Ident, Type}; +use crate::define_keyword; + +define_keyword!(Open, OpenKeyword, "open"); + pub struct OpenDelegateEntry { pub open: Ident, pub components: Punctuated, diff --git a/crates/cgp-macro-core/src/types/keyword.rs b/crates/cgp-macro-core/src/types/keyword.rs new file mode 100644 index 00000000..6a936d4c --- /dev/null +++ b/crates/cgp-macro-core/src/types/keyword.rs @@ -0,0 +1,30 @@ +use core::marker::PhantomData; + +use proc_macro2::Span; +use syn::parse::{Parse, ParseStream}; +use syn::{Error, Ident}; + +use crate::traits::IsKeyword; + +pub struct Keyword { + pub span: Span, + pub phantom: PhantomData, +} + +impl Parse for Keyword +where + K: IsKeyword, +{ + fn parse(input: ParseStream) -> syn::Result { + let ident: Ident = input.parse()?; + + if ident != K::IDENT { + return Err(Error::new_spanned(ident, &format!("expect keyword: `{}`", K::IDENT))); + } + + Ok(Self { + span: ident.span(), + phantom: PhantomData, + }) + } +} diff --git a/crates/cgp-macro-core/src/types/mod.rs b/crates/cgp-macro-core/src/types/mod.rs index 515c0695..711091ff 100644 --- a/crates/cgp-macro-core/src/types/mod.rs +++ b/crates/cgp-macro-core/src/types/mod.rs @@ -1,7 +1,6 @@ pub mod delegate_component; pub mod generics; +pub mod keyword; pub mod namespace; pub mod path; pub mod symbol; - -pub use symbol::*; From 3f6675f97f830f9732d8b087f4aabe780681e432 Mon Sep 17 00:00:00 2001 From: Soares Chen Date: Thu, 21 May 2026 22:50:50 +0200 Subject: [PATCH 31/81] Implement PeekKeyword --- crates/cgp-macro-core/src/macros.rs | 3 +-- crates/cgp-macro-core/src/traits/keyword.rs | 21 +++++++++++++++++++ crates/cgp-macro-core/src/types/keyword.rs | 5 ++++- .../src/types/path/path_head_or_type.rs | 1 + .../cgp-macro-core/src/types/path/unipath.rs | 6 ++++-- crates/cgp-macro-lib/src/parse/path.rs | 5 +---- 6 files changed, 32 insertions(+), 9 deletions(-) diff --git a/crates/cgp-macro-core/src/macros.rs b/crates/cgp-macro-core/src/macros.rs index d0814484..4edeed81 100644 --- a/crates/cgp-macro-core/src/macros.rs +++ b/crates/cgp-macro-core/src/macros.rs @@ -31,6 +31,5 @@ macro_rules! define_keyword { } pub type $struct_ident = $crate::types::keyword::Keyword<$impl_ident>; - - } + }; } diff --git a/crates/cgp-macro-core/src/traits/keyword.rs b/crates/cgp-macro-core/src/traits/keyword.rs index c7e2e6a2..fc76588f 100644 --- a/crates/cgp-macro-core/src/traits/keyword.rs +++ b/crates/cgp-macro-core/src/traits/keyword.rs @@ -1,3 +1,24 @@ +use syn::Ident; +use syn::parse::ParseBuffer; + +use crate::types::keyword::Keyword; + pub trait IsKeyword { const IDENT: &'static str; } + +pub trait PeekKeyword { + fn peek(&self, keyword: K) -> bool; +} + +impl<'a, K: IsKeyword> PeekKeyword> for ParseBuffer<'a> { + fn peek(&self, _keyword: Keyword) -> bool { + if let Ok(ident) = self.fork().parse::() + && ident == K::IDENT + { + true + } else { + false + } + } +} diff --git a/crates/cgp-macro-core/src/types/keyword.rs b/crates/cgp-macro-core/src/types/keyword.rs index 6a936d4c..ded752ae 100644 --- a/crates/cgp-macro-core/src/types/keyword.rs +++ b/crates/cgp-macro-core/src/types/keyword.rs @@ -19,7 +19,10 @@ where let ident: Ident = input.parse()?; if ident != K::IDENT { - return Err(Error::new_spanned(ident, &format!("expect keyword: `{}`", K::IDENT))); + return Err(Error::new_spanned( + ident, + format!("expect keyword: `{}`", K::IDENT), + )); } Ok(Self { diff --git a/crates/cgp-macro-core/src/types/path/path_head_or_type.rs b/crates/cgp-macro-core/src/types/path/path_head_or_type.rs index 41cffc45..7ff473c6 100644 --- a/crates/cgp-macro-core/src/types/path/path_head_or_type.rs +++ b/crates/cgp-macro-core/src/types/path/path_head_or_type.rs @@ -5,6 +5,7 @@ use syn::token::At; use crate::types::generics::ImplGenerics; use crate::types::path::PathHead; +#[allow(clippy::large_enum_variant)] #[derive(Debug, Clone)] pub enum PathHeadOrType { PathHead(PathHead), diff --git a/crates/cgp-macro-core/src/types/path/unipath.rs b/crates/cgp-macro-core/src/types/path/unipath.rs index e1d2d35a..b0155216 100644 --- a/crates/cgp-macro-core/src/types/path/unipath.rs +++ b/crates/cgp-macro-core/src/types/path/unipath.rs @@ -13,13 +13,15 @@ pub struct UniPath { pub elements: Punctuated, } -impl UniPath { - pub fn from_iter(elements: impl IntoIterator) -> Self { +impl FromIterator for UniPath { + fn from_iter>(elements: T) -> Self { Self { elements: Punctuated::from_iter(elements), } } +} +impl UniPath { pub fn append_type(&mut self, ty: Type) { self.elements.push(PathElement::Type(ty)); } diff --git a/crates/cgp-macro-lib/src/parse/path.rs b/crates/cgp-macro-lib/src/parse/path.rs index 8353350c..ccf5d4d5 100644 --- a/crates/cgp-macro-lib/src/parse/path.rs +++ b/crates/cgp-macro-lib/src/parse/path.rs @@ -46,10 +46,7 @@ pub fn path_head_to_prefix(path_head: &PathHead) -> Vec paths - .iter() - .flat_map(|path| path_head_to_prefix(path)) - .collect(), + PathHead::Group(paths) => paths.iter().flat_map(path_head_to_prefix).collect(), PathHead::End => { vec![ComponentPath { path_type: quote! { __Wildcard__ }, From 21964516f9180d2caba8e18d1d3b524900c8493b Mon Sep 17 00:00:00 2001 From: Soares Chen Date: Thu, 21 May 2026 22:56:53 +0200 Subject: [PATCH 32/81] Implement NamespaceDelegateEntry --- .../src/types/delegate_component/entry/mod.rs | 2 ++ .../delegate_component/entry/namespace.rs | 27 +++++++++++++++++++ .../types/delegate_component/entry/open.rs | 20 ++++++++++++-- 3 files changed, 47 insertions(+), 2 deletions(-) create mode 100644 crates/cgp-macro-core/src/types/delegate_component/entry/namespace.rs diff --git a/crates/cgp-macro-core/src/types/delegate_component/entry/mod.rs b/crates/cgp-macro-core/src/types/delegate_component/entry/mod.rs index 7a7b2fc2..b587f475 100644 --- a/crates/cgp-macro-core/src/types/delegate_component/entry/mod.rs +++ b/crates/cgp-macro-core/src/types/delegate_component/entry/mod.rs @@ -1,11 +1,13 @@ mod combined; mod direct; mod mode; +mod namespace; mod normal; mod open; pub use combined::*; pub use direct::*; pub use mode::*; +pub use namespace::*; pub use normal::*; pub use open::*; diff --git a/crates/cgp-macro-core/src/types/delegate_component/entry/namespace.rs b/crates/cgp-macro-core/src/types/delegate_component/entry/namespace.rs new file mode 100644 index 00000000..dc5099b9 --- /dev/null +++ b/crates/cgp-macro-core/src/types/delegate_component/entry/namespace.rs @@ -0,0 +1,27 @@ +use syn::Ident; +use syn::parse::Parse; +use syn::token::Semi; + +use crate::define_keyword; + +define_keyword!(Namespace, NamespaceKeyword, "namespace"); + +pub struct NamespaceDelegateEntry { + pub namespace: Namespace, + pub ident: Ident, + pub semi: Semi, +} + +impl Parse for NamespaceDelegateEntry { + fn parse(input: syn::parse::ParseStream) -> syn::Result { + let namespace = input.parse()?; + let ident = input.parse()?; + let semi = input.parse()?; + + Ok(Self { + namespace, + ident, + semi, + }) + } +} diff --git a/crates/cgp-macro-core/src/types/delegate_component/entry/open.rs b/crates/cgp-macro-core/src/types/delegate_component/entry/open.rs index 63acca12..9bf4672f 100644 --- a/crates/cgp-macro-core/src/types/delegate_component/entry/open.rs +++ b/crates/cgp-macro-core/src/types/delegate_component/entry/open.rs @@ -1,13 +1,29 @@ +use syn::Type; +use syn::parse::{Parse, ParseStream}; use syn::punctuated::Punctuated; use syn::token::{Comma, Semi}; -use syn::{Ident, Type}; use crate::define_keyword; define_keyword!(Open, OpenKeyword, "open"); pub struct OpenDelegateEntry { - pub open: Ident, + pub open: Open, pub components: Punctuated, pub semi: Semi, } + +impl Parse for OpenDelegateEntry { + fn parse(input: ParseStream) -> syn::Result { + let open = input.parse()?; + + let components: Punctuated = Punctuated::parse_separated_nonempty(input)?; + let semi = input.parse()?; + + Ok(Self { + open, + components, + semi, + }) + } +} From 1b1d3656f1cc2b2f2d8514ea66e112fc85c3eba8 Mon Sep 17 00:00:00 2001 From: Soares Chen Date: Thu, 21 May 2026 23:14:52 +0200 Subject: [PATCH 33/81] Implement EvalDelegateEntry --- crates/cgp-macro-core/src/exports.rs | 9 +++--- .../types/delegate_component/entry/eval.rs | 11 +++++++ .../src/types/delegate_component/entry/mod.rs | 2 ++ .../delegate_component/entry/namespace.rs | 30 ++++++++++++++++++- .../types/delegate_component/entry/open.rs | 29 +++++++++++++++++- 5 files changed, 75 insertions(+), 6 deletions(-) create mode 100644 crates/cgp-macro-core/src/types/delegate_component/entry/eval.rs diff --git a/crates/cgp-macro-core/src/exports.rs b/crates/cgp-macro-core/src/exports.rs index 7951ad81..8e0eb332 100644 --- a/crates/cgp-macro-core/src/exports.rs +++ b/crates/cgp-macro-core/src/exports.rs @@ -1,9 +1,10 @@ use crate::export_constructs; export_constructs! { - Nil => ε, - Cons => π, - Chars => ζ, - Symbol => ψ, + Nil, + Cons, + Chars, + Symbol, PathCons, + RedirectLookup, } diff --git a/crates/cgp-macro-core/src/types/delegate_component/entry/eval.rs b/crates/cgp-macro-core/src/types/delegate_component/entry/eval.rs new file mode 100644 index 00000000..5656a862 --- /dev/null +++ b/crates/cgp-macro-core/src/types/delegate_component/entry/eval.rs @@ -0,0 +1,11 @@ +use syn::{Generics, Type}; + +pub struct EvaluatedDelegateEntry { + pub generics: Generics, + pub key: Type, + pub value: Type, +} + +pub trait EvalDelegateEntry { + fn eval(&self, context_type: &Type) -> syn::Result>; +} diff --git a/crates/cgp-macro-core/src/types/delegate_component/entry/mod.rs b/crates/cgp-macro-core/src/types/delegate_component/entry/mod.rs index b587f475..a57949cc 100644 --- a/crates/cgp-macro-core/src/types/delegate_component/entry/mod.rs +++ b/crates/cgp-macro-core/src/types/delegate_component/entry/mod.rs @@ -1,5 +1,6 @@ mod combined; mod direct; +mod eval; mod mode; mod namespace; mod normal; @@ -7,6 +8,7 @@ mod open; pub use combined::*; pub use direct::*; +pub use eval::*; pub use mode::*; pub use namespace::*; pub use normal::*; diff --git a/crates/cgp-macro-core/src/types/delegate_component/entry/namespace.rs b/crates/cgp-macro-core/src/types/delegate_component/entry/namespace.rs index dc5099b9..329e5ede 100644 --- a/crates/cgp-macro-core/src/types/delegate_component/entry/namespace.rs +++ b/crates/cgp-macro-core/src/types/delegate_component/entry/namespace.rs @@ -1,8 +1,9 @@ -use syn::Ident; use syn::parse::Parse; use syn::token::Semi; +use syn::{Ident, Type, parse_quote}; use crate::define_keyword; +use crate::types::delegate_component::{EvalDelegateEntry, EvaluatedDelegateEntry}; define_keyword!(Namespace, NamespaceKeyword, "namespace"); @@ -25,3 +26,30 @@ impl Parse for NamespaceDelegateEntry { }) } } + +impl EvalDelegateEntry for NamespaceDelegateEntry { + fn eval(&self, context_type: &Type) -> syn::Result> { + let namespace_ident = if &self.ident == "default" { + Ident::new("DefaultNamespace", self.ident.span()) + } else { + self.ident.clone() + }; + + let key = parse_quote!(__Component__); + let generics = parse_quote! { + <__Component__: #namespace_ident< #context_type >> + }; + + let value = parse_quote! { + < __Component__ as #namespace_ident< #context_type >>::Provider + }; + + let entry = EvaluatedDelegateEntry { + generics, + key, + value, + }; + + Ok(vec![entry]) + } +} diff --git a/crates/cgp-macro-core/src/types/delegate_component/entry/open.rs b/crates/cgp-macro-core/src/types/delegate_component/entry/open.rs index 9bf4672f..154afd7f 100644 --- a/crates/cgp-macro-core/src/types/delegate_component/entry/open.rs +++ b/crates/cgp-macro-core/src/types/delegate_component/entry/open.rs @@ -1,9 +1,11 @@ -use syn::Type; use syn::parse::{Parse, ParseStream}; use syn::punctuated::Punctuated; use syn::token::{Comma, Semi}; +use syn::{Type, parse_quote}; use crate::define_keyword; +use crate::exports::{Nil, PathCons, RedirectLookup}; +use crate::types::delegate_component::{EvalDelegateEntry, EvaluatedDelegateEntry}; define_keyword!(Open, OpenKeyword, "open"); @@ -27,3 +29,28 @@ impl Parse for OpenDelegateEntry { }) } } + +impl EvalDelegateEntry for OpenDelegateEntry { + fn eval(&self, context_type: &Type) -> syn::Result> { + let mut entries = Vec::new(); + + for component in &self.components { + let value: Type = parse_quote! { + #RedirectLookup< + #context_type, + #PathCons<#component, #Nil>, + > + }; + + let key = component.clone(); + + entries.push(EvaluatedDelegateEntry { + generics: Default::default(), + key, + value, + }) + } + + Ok(entries) + } +} From 45d649f4d49c01022067d533813e7117cd9ed070 Mon Sep 17 00:00:00 2001 From: Soares Chen Date: Thu, 21 May 2026 23:25:38 +0200 Subject: [PATCH 34/81] Reorganize DelegateKey constructs --- .../types/delegate_component/entry/normal.rs | 11 ++- .../src/types/delegate_component/key.rs | 72 ------------------- .../types/delegate_component/key/combined.rs | 31 ++++++++ .../src/types/delegate_component/key/mod.rs | 9 +++ .../src/types/delegate_component/key/multi.rs | 20 ++++++ .../src/types/delegate_component/key/path.rs | 21 ++++++ .../types/delegate_component/key/single.rs | 18 +++++ 7 files changed, 109 insertions(+), 73 deletions(-) delete mode 100644 crates/cgp-macro-core/src/types/delegate_component/key.rs create mode 100644 crates/cgp-macro-core/src/types/delegate_component/key/combined.rs create mode 100644 crates/cgp-macro-core/src/types/delegate_component/key/mod.rs create mode 100644 crates/cgp-macro-core/src/types/delegate_component/key/multi.rs create mode 100644 crates/cgp-macro-core/src/types/delegate_component/key/path.rs create mode 100644 crates/cgp-macro-core/src/types/delegate_component/key/single.rs diff --git a/crates/cgp-macro-core/src/types/delegate_component/entry/normal.rs b/crates/cgp-macro-core/src/types/delegate_component/entry/normal.rs index 5f4832e2..f15b451a 100644 --- a/crates/cgp-macro-core/src/types/delegate_component/entry/normal.rs +++ b/crates/cgp-macro-core/src/types/delegate_component/entry/normal.rs @@ -1,9 +1,18 @@ +use syn::Type; use syn::token::Colon; -use crate::types::delegate_component::{DelegateKey, DelegateValue}; +use crate::types::delegate_component::{ + DelegateKey, DelegateValue, EvalDelegateEntry, EvaluatedDelegateEntry, +}; pub struct NormalDelegateEntry { pub key: DelegateKey, pub colon: Colon, pub value: DelegateValue, } + +impl EvalDelegateEntry for NormalDelegateEntry { + fn eval(&self, context_type: &Type) -> syn::Result> { + todo!() + } +} diff --git a/crates/cgp-macro-core/src/types/delegate_component/key.rs b/crates/cgp-macro-core/src/types/delegate_component/key.rs deleted file mode 100644 index 526fa1e7..00000000 --- a/crates/cgp-macro-core/src/types/delegate_component/key.rs +++ /dev/null @@ -1,72 +0,0 @@ -use syn::bracketed; -use syn::parse::discouraged::Speculative; -use syn::parse::{Parse, ParseStream}; -use syn::punctuated::Punctuated; -use syn::token::{At, Bracket, Comma, Type}; - -use crate::types::generics::ImplGenerics; -use crate::types::path::PathHead; - -pub enum DelegateKey { - Single(SingleDelegateKey), - Multi(MultiDelegateKey), - Path(PathDelegateKey), -} - -pub struct SingleDelegateKey { - pub generics: ImplGenerics, - pub ty: Type, -} - -pub struct MultiDelegateKey { - pub keys: Punctuated, -} - -pub struct PathDelegateKey { - pub generics: ImplGenerics, - pub at: At, - pub path: PathHead, -} - -impl Parse for DelegateKey { - fn parse(input: ParseStream) -> syn::Result { - let fork = input.fork(); - let generics: ImplGenerics = fork.parse()?; - - let key = if fork.peek(At) { - input.advance_to(&fork); - - let at = input.parse()?; - let path = input.parse()?; - - Self::Path(PathDelegateKey { generics, at, path }) - } else if input.peek(Bracket) { - let keys = input.parse()?; - Self::Multi(keys) - } else { - let key = input.parse()?; - Self::Single(key) - }; - - Ok(key) - } -} - -impl Parse for SingleDelegateKey { - fn parse(input: ParseStream) -> syn::Result { - let generics = input.parse()?; - let ty = input.parse()?; - - Ok(Self { generics, ty }) - } -} - -impl Parse for MultiDelegateKey { - fn parse(input: ParseStream) -> syn::Result { - let body; - bracketed!(body in input); - let keys = Punctuated::parse_terminated(&body)?; - - Ok(Self { keys }) - } -} diff --git a/crates/cgp-macro-core/src/types/delegate_component/key/combined.rs b/crates/cgp-macro-core/src/types/delegate_component/key/combined.rs new file mode 100644 index 00000000..150ab82d --- /dev/null +++ b/crates/cgp-macro-core/src/types/delegate_component/key/combined.rs @@ -0,0 +1,31 @@ +use syn::parse::{Parse, ParseStream}; +use syn::token::{At, Bracket}; + +use crate::types::delegate_component::{MultiDelegateKey, PathDelegateKey, SingleDelegateKey}; +use crate::types::generics::ImplGenerics; + +pub enum DelegateKey { + Single(SingleDelegateKey), + Multi(MultiDelegateKey), + Path(PathDelegateKey), +} + +impl Parse for DelegateKey { + fn parse(input: ParseStream) -> syn::Result { + let fork = input.fork(); + let _generics: ImplGenerics = fork.parse()?; + + let key = if fork.peek(At) { + let path = input.parse()?; + Self::Path(path) + } else if input.peek(Bracket) { + let keys = input.parse()?; + Self::Multi(keys) + } else { + let key = input.parse()?; + Self::Single(key) + }; + + Ok(key) + } +} diff --git a/crates/cgp-macro-core/src/types/delegate_component/key/mod.rs b/crates/cgp-macro-core/src/types/delegate_component/key/mod.rs new file mode 100644 index 00000000..fb2926be --- /dev/null +++ b/crates/cgp-macro-core/src/types/delegate_component/key/mod.rs @@ -0,0 +1,9 @@ +mod combined; +mod multi; +mod path; +mod single; + +pub use combined::*; +pub use multi::*; +pub use path::*; +pub use single::*; diff --git a/crates/cgp-macro-core/src/types/delegate_component/key/multi.rs b/crates/cgp-macro-core/src/types/delegate_component/key/multi.rs new file mode 100644 index 00000000..a5659417 --- /dev/null +++ b/crates/cgp-macro-core/src/types/delegate_component/key/multi.rs @@ -0,0 +1,20 @@ +use syn::bracketed; +use syn::parse::{Parse, ParseStream}; +use syn::punctuated::Punctuated; +use syn::token::Comma; + +use crate::types::delegate_component::SingleDelegateKey; + +pub struct MultiDelegateKey { + pub keys: Punctuated, +} + +impl Parse for MultiDelegateKey { + fn parse(input: ParseStream) -> syn::Result { + let body; + bracketed!(body in input); + let keys = Punctuated::parse_terminated(&body)?; + + Ok(Self { keys }) + } +} diff --git a/crates/cgp-macro-core/src/types/delegate_component/key/path.rs b/crates/cgp-macro-core/src/types/delegate_component/key/path.rs new file mode 100644 index 00000000..2e61fad8 --- /dev/null +++ b/crates/cgp-macro-core/src/types/delegate_component/key/path.rs @@ -0,0 +1,21 @@ +use syn::parse::{Parse, ParseStream}; +use syn::token::At; + +use crate::types::generics::ImplGenerics; +use crate::types::path::PathHead; + +pub struct PathDelegateKey { + pub generics: ImplGenerics, + pub at: At, + pub path: PathHead, +} + +impl Parse for PathDelegateKey { + fn parse(input: ParseStream) -> syn::Result { + let generics = input.parse()?; + let at = input.parse()?; + let path = input.parse()?; + + Ok(Self { generics, at, path }) + } +} diff --git a/crates/cgp-macro-core/src/types/delegate_component/key/single.rs b/crates/cgp-macro-core/src/types/delegate_component/key/single.rs new file mode 100644 index 00000000..02ba7ac1 --- /dev/null +++ b/crates/cgp-macro-core/src/types/delegate_component/key/single.rs @@ -0,0 +1,18 @@ +use syn::Type; +use syn::parse::{Parse, ParseStream}; + +use crate::types::generics::ImplGenerics; + +pub struct SingleDelegateKey { + pub generics: ImplGenerics, + pub ty: Type, +} + +impl Parse for SingleDelegateKey { + fn parse(input: ParseStream) -> syn::Result { + let generics = input.parse()?; + let ty = input.parse()?; + + Ok(Self { generics, ty }) + } +} From 6880d6b90cf8b32db70a7c87ae6f84f2b7402409 Mon Sep 17 00:00:00 2001 From: Soares Chen Date: Thu, 21 May 2026 23:37:55 +0200 Subject: [PATCH 35/81] Implement EvalDelegateKey --- .../src/functions}/merge_generics.rs | 0 crates/cgp-macro-core/src/functions/mod.rs | 3 +++ crates/cgp-macro-core/src/lib.rs | 1 + .../types/delegate_component/key/combined.rs | 14 ++++++++++- .../src/types/delegate_component/key/eval.rs | 10 ++++++++ .../src/types/delegate_component/key/mod.rs | 2 ++ .../src/types/delegate_component/key/multi.rs | 19 +++++++++++++- .../src/types/delegate_component/key/path.rs | 25 +++++++++++++++++++ .../types/delegate_component/key/single.rs | 12 +++++++++ .../src/check_components/derive.rs | 2 +- .../src/delegate_components/impl_delegate.rs | 2 +- .../src/delegate_components/mod.rs | 2 -- .../src/parse/delegate_components.rs | 2 +- 13 files changed, 87 insertions(+), 7 deletions(-) rename crates/{cgp-macro-lib/src/delegate_components => cgp-macro-core/src/functions}/merge_generics.rs (100%) create mode 100644 crates/cgp-macro-core/src/functions/mod.rs create mode 100644 crates/cgp-macro-core/src/types/delegate_component/key/eval.rs diff --git a/crates/cgp-macro-lib/src/delegate_components/merge_generics.rs b/crates/cgp-macro-core/src/functions/merge_generics.rs similarity index 100% rename from crates/cgp-macro-lib/src/delegate_components/merge_generics.rs rename to crates/cgp-macro-core/src/functions/merge_generics.rs diff --git a/crates/cgp-macro-core/src/functions/mod.rs b/crates/cgp-macro-core/src/functions/mod.rs new file mode 100644 index 00000000..f5b39fc2 --- /dev/null +++ b/crates/cgp-macro-core/src/functions/mod.rs @@ -0,0 +1,3 @@ +mod merge_generics; + +pub use merge_generics::*; diff --git a/crates/cgp-macro-core/src/lib.rs b/crates/cgp-macro-core/src/lib.rs index a5b7d4ff..a6dbd9e7 100644 --- a/crates/cgp-macro-core/src/lib.rs +++ b/crates/cgp-macro-core/src/lib.rs @@ -1,6 +1,7 @@ #![allow(mixed_script_confusables)] pub mod exports; +pub mod functions; pub mod macros; pub mod traits; pub mod types; diff --git a/crates/cgp-macro-core/src/types/delegate_component/key/combined.rs b/crates/cgp-macro-core/src/types/delegate_component/key/combined.rs index 150ab82d..33169641 100644 --- a/crates/cgp-macro-core/src/types/delegate_component/key/combined.rs +++ b/crates/cgp-macro-core/src/types/delegate_component/key/combined.rs @@ -1,7 +1,9 @@ use syn::parse::{Parse, ParseStream}; use syn::token::{At, Bracket}; -use crate::types::delegate_component::{MultiDelegateKey, PathDelegateKey, SingleDelegateKey}; +use crate::types::delegate_component::{ + EvalDelegateKey, EvaluatedDelegateKey, MultiDelegateKey, PathDelegateKey, SingleDelegateKey, +}; use crate::types::generics::ImplGenerics; pub enum DelegateKey { @@ -29,3 +31,13 @@ impl Parse for DelegateKey { Ok(key) } } + +impl EvalDelegateKey for DelegateKey { + fn eval(&self) -> syn::Result> { + match self { + Self::Single(key) => key.eval(), + Self::Multi(key) => key.eval(), + Self::Path(key) => key.eval(), + } + } +} diff --git a/crates/cgp-macro-core/src/types/delegate_component/key/eval.rs b/crates/cgp-macro-core/src/types/delegate_component/key/eval.rs new file mode 100644 index 00000000..99159104 --- /dev/null +++ b/crates/cgp-macro-core/src/types/delegate_component/key/eval.rs @@ -0,0 +1,10 @@ +use syn::{Generics, Type}; + +pub struct EvaluatedDelegateKey { + pub generics: Generics, + pub key: Type, +} + +pub trait EvalDelegateKey { + fn eval(&self) -> syn::Result>; +} diff --git a/crates/cgp-macro-core/src/types/delegate_component/key/mod.rs b/crates/cgp-macro-core/src/types/delegate_component/key/mod.rs index fb2926be..fc077b08 100644 --- a/crates/cgp-macro-core/src/types/delegate_component/key/mod.rs +++ b/crates/cgp-macro-core/src/types/delegate_component/key/mod.rs @@ -1,9 +1,11 @@ mod combined; +mod eval; mod multi; mod path; mod single; pub use combined::*; +pub use eval::*; pub use multi::*; pub use path::*; pub use single::*; diff --git a/crates/cgp-macro-core/src/types/delegate_component/key/multi.rs b/crates/cgp-macro-core/src/types/delegate_component/key/multi.rs index a5659417..a904f9d9 100644 --- a/crates/cgp-macro-core/src/types/delegate_component/key/multi.rs +++ b/crates/cgp-macro-core/src/types/delegate_component/key/multi.rs @@ -3,7 +3,7 @@ use syn::parse::{Parse, ParseStream}; use syn::punctuated::Punctuated; use syn::token::Comma; -use crate::types::delegate_component::SingleDelegateKey; +use crate::types::delegate_component::{EvalDelegateKey, EvaluatedDelegateKey, SingleDelegateKey}; pub struct MultiDelegateKey { pub keys: Punctuated, @@ -18,3 +18,20 @@ impl Parse for MultiDelegateKey { Ok(Self { keys }) } } + +impl EvalDelegateKey for MultiDelegateKey { + fn eval(&self) -> syn::Result> { + let mut keys = Vec::new(); + + for key in &self.keys { + let key = EvaluatedDelegateKey { + generics: key.generics.generics.clone(), + key: key.ty.clone(), + }; + + keys.push(key) + } + + Ok(keys) + } +} diff --git a/crates/cgp-macro-core/src/types/delegate_component/key/path.rs b/crates/cgp-macro-core/src/types/delegate_component/key/path.rs index 2e61fad8..fb4f5868 100644 --- a/crates/cgp-macro-core/src/types/delegate_component/key/path.rs +++ b/crates/cgp-macro-core/src/types/delegate_component/key/path.rs @@ -1,6 +1,9 @@ use syn::parse::{Parse, ParseStream}; use syn::token::At; +use syn::{Type, parse_quote}; +use crate::functions::merge_generics; +use crate::types::delegate_component::{EvalDelegateKey, EvaluatedDelegateKey}; use crate::types::generics::ImplGenerics; use crate::types::path::PathHead; @@ -19,3 +22,25 @@ impl Parse for PathDelegateKey { Ok(Self { generics, at, path }) } } + +impl EvalDelegateKey for PathDelegateKey { + fn eval(&self) -> syn::Result> { + let paths = self.path.into_paths(); + let outer_generics = &self.generics; + let mut keys = Vec::new(); + + for (inner_generics, path) in paths { + let generics = merge_generics(outer_generics, &inner_generics); + let path_type: Type = parse_quote!(#path); + + let key = EvaluatedDelegateKey { + generics, + key: path_type, + }; + + keys.push(key) + } + + Ok(keys) + } +} diff --git a/crates/cgp-macro-core/src/types/delegate_component/key/single.rs b/crates/cgp-macro-core/src/types/delegate_component/key/single.rs index 02ba7ac1..0cddac02 100644 --- a/crates/cgp-macro-core/src/types/delegate_component/key/single.rs +++ b/crates/cgp-macro-core/src/types/delegate_component/key/single.rs @@ -1,6 +1,7 @@ use syn::Type; use syn::parse::{Parse, ParseStream}; +use crate::types::delegate_component::{EvalDelegateKey, EvaluatedDelegateKey}; use crate::types::generics::ImplGenerics; pub struct SingleDelegateKey { @@ -16,3 +17,14 @@ impl Parse for SingleDelegateKey { Ok(Self { generics, ty }) } } + +impl EvalDelegateKey for SingleDelegateKey { + fn eval(&self) -> syn::Result> { + let key = EvaluatedDelegateKey { + generics: self.generics.generics.clone(), + key: self.ty.clone(), + }; + + Ok(vec![key]) + } +} diff --git a/crates/cgp-macro-lib/src/check_components/derive.rs b/crates/cgp-macro-lib/src/check_components/derive.rs index 28b70a2e..30cbe64d 100644 --- a/crates/cgp-macro-lib/src/check_components/derive.rs +++ b/crates/cgp-macro-lib/src/check_components/derive.rs @@ -1,10 +1,10 @@ +use cgp_macro_core::functions::merge_generics; use quote::quote; use syn::punctuated::Punctuated; use syn::token::Comma; use syn::{ItemImpl, ItemTrait, Type, parse2}; use crate::check_components::override_span; -use crate::delegate_components::merge_generics; use crate::parse::{CheckComponents, CheckEntry}; pub fn derive_check_components(spec: &CheckComponents) -> syn::Result<(ItemTrait, Vec)> { diff --git a/crates/cgp-macro-lib/src/delegate_components/impl_delegate.rs b/crates/cgp-macro-lib/src/delegate_components/impl_delegate.rs index 1402c97b..c35a8ca0 100644 --- a/crates/cgp-macro-lib/src/delegate_components/impl_delegate.rs +++ b/crates/cgp-macro-lib/src/delegate_components/impl_delegate.rs @@ -2,6 +2,7 @@ use alloc::boxed::Box; use alloc::vec; use alloc::vec::Vec; +use cgp_macro_core::functions::merge_generics; use cgp_macro_core::types::generics::ImplGenerics; use proc_macro2::TokenStream; use quote::{ToTokens, quote}; @@ -10,7 +11,6 @@ use syn::token::Comma; use syn::{ImplItem, ImplItemType, ItemImpl, Path, Type, parse2}; use crate::delegate_components::define_struct; -use crate::delegate_components::merge_generics::merge_generics; use crate::parse::{DelegateEntry, DelegateKey, DelegateMode, DelegateValue}; pub fn impl_delegate_components( diff --git a/crates/cgp-macro-lib/src/delegate_components/mod.rs b/crates/cgp-macro-lib/src/delegate_components/mod.rs index 828d2726..ab2ea3e7 100644 --- a/crates/cgp-macro-lib/src/delegate_components/mod.rs +++ b/crates/cgp-macro-lib/src/delegate_components/mod.rs @@ -1,7 +1,5 @@ mod define_struct; mod impl_delegate; -mod merge_generics; pub use define_struct::*; pub use impl_delegate::*; -pub use merge_generics::*; diff --git a/crates/cgp-macro-lib/src/parse/delegate_components.rs b/crates/cgp-macro-lib/src/parse/delegate_components.rs index 455b8e52..97b19f8d 100644 --- a/crates/cgp-macro-lib/src/parse/delegate_components.rs +++ b/crates/cgp-macro-lib/src/parse/delegate_components.rs @@ -1,5 +1,6 @@ use core::iter; +use cgp_macro_core::functions::merge_generics; use cgp_macro_core::types::generics::{ImplGenerics, TypeGenerics}; use proc_macro2::{Span, TokenStream}; use quote::{ToTokens, TokenStreamExt, quote}; @@ -9,7 +10,6 @@ use syn::punctuated::Punctuated; use syn::token::{At, Bracket, Colon, Comma, Gt, Lt, RArrow, Semi}; use syn::{Error, Generics, Ident, Token, Type, braced, bracketed, parse_quote, parse2}; -use crate::delegate_components::merge_generics; use crate::parse::{ComponentPaths, SimpleType}; pub struct DelegateComponents { From ce512a064f821b4e88054969bf3765100929d478 Mon Sep 17 00:00:00 2001 From: Soares Chen Date: Fri, 22 May 2026 23:20:42 +0200 Subject: [PATCH 36/81] Reorganize DelegateValue constructs --- .../types/delegate_component/entry/normal.rs | 13 +++++++--- .../delegate_component/value/combined.rs | 24 +++++++++++++++++ .../{value.rs => value/inner_entries.rs} | 26 +++---------------- .../src/types/delegate_component/value/mod.rs | 5 ++++ 4 files changed, 42 insertions(+), 26 deletions(-) create mode 100644 crates/cgp-macro-core/src/types/delegate_component/value/combined.rs rename crates/cgp-macro-core/src/types/delegate_component/{value.rs => value/inner_entries.rs} (63%) create mode 100644 crates/cgp-macro-core/src/types/delegate_component/value/mod.rs diff --git a/crates/cgp-macro-core/src/types/delegate_component/entry/normal.rs b/crates/cgp-macro-core/src/types/delegate_component/entry/normal.rs index f15b451a..d3e1877a 100644 --- a/crates/cgp-macro-core/src/types/delegate_component/entry/normal.rs +++ b/crates/cgp-macro-core/src/types/delegate_component/entry/normal.rs @@ -2,7 +2,7 @@ use syn::Type; use syn::token::Colon; use crate::types::delegate_component::{ - DelegateKey, DelegateValue, EvalDelegateEntry, EvaluatedDelegateEntry, + DelegateKey, DelegateValue, EvalDelegateEntry, EvalDelegateKey, EvaluatedDelegateEntry, }; pub struct NormalDelegateEntry { @@ -12,7 +12,14 @@ pub struct NormalDelegateEntry { } impl EvalDelegateEntry for NormalDelegateEntry { - fn eval(&self, context_type: &Type) -> syn::Result> { - todo!() + fn eval(&self, _context_type: &Type) -> syn::Result> { + let keys = self.key.eval()?; + let entries = Vec::new(); + + for _key in keys { + todo!() + } + + Ok(entries) } } diff --git a/crates/cgp-macro-core/src/types/delegate_component/value/combined.rs b/crates/cgp-macro-core/src/types/delegate_component/value/combined.rs new file mode 100644 index 00000000..51c7c9c8 --- /dev/null +++ b/crates/cgp-macro-core/src/types/delegate_component/value/combined.rs @@ -0,0 +1,24 @@ +use syn::Type; +use syn::parse::discouraged::Speculative; +use syn::parse::{Parse, ParseStream}; + +use crate::types::delegate_component::DelegateValueWithInnerEntries; + +pub enum DelegateValue { + Type(Type), + WithInner(DelegateValueWithInnerEntries), +} + +impl Parse for DelegateValue { + fn parse(input: ParseStream) -> syn::Result { + let fork = input.fork(); + + if let Ok(value) = fork.parse::() { + input.advance_to(&fork); + return Ok(Self::WithInner(value)); + } + + let ty: Type = input.parse()?; + Ok(Self::Type(ty)) + } +} diff --git a/crates/cgp-macro-core/src/types/delegate_component/value.rs b/crates/cgp-macro-core/src/types/delegate_component/value/inner_entries.rs similarity index 63% rename from crates/cgp-macro-core/src/types/delegate_component/value.rs rename to crates/cgp-macro-core/src/types/delegate_component/value/inner_entries.rs index 07ad116f..6a4df32c 100644 --- a/crates/cgp-macro-core/src/types/delegate_component/value.rs +++ b/crates/cgp-macro-core/src/types/delegate_component/value/inner_entries.rs @@ -1,38 +1,18 @@ -use syn::parse::discouraged::Speculative; use syn::parse::{Parse, ParseStream}; use syn::punctuated::Punctuated; use syn::token::{Comma, Gt, Lt}; -use syn::{Error, Generics, Ident, Type, braced}; +use syn::{Error, Ident, braced}; use crate::types::delegate_component::DelegateEntry; use crate::types::generics::TypeGenerics; -pub enum DelegateValue { - Type(Type), - WithInner(DelegateValueWithInnerEntries), -} - pub struct DelegateValueWithInnerEntries { pub wrapper_ident: Ident, pub struct_ident: Ident, - pub struct_generics: Generics, + pub struct_generics: TypeGenerics, pub entries: Punctuated, } -impl Parse for DelegateValue { - fn parse(input: ParseStream) -> syn::Result { - let fork = input.fork(); - - if let Ok(value) = fork.parse::() { - input.advance_to(&fork); - return Ok(Self::WithInner(value)); - } - - let ty: Type = input.parse()?; - Ok(Self::Type(ty)) - } -} - impl Parse for DelegateValueWithInnerEntries { fn parse(input: ParseStream) -> syn::Result { let wrapper_ident = input.parse()?; @@ -61,7 +41,7 @@ impl Parse for DelegateValueWithInnerEntries { Ok(Self { wrapper_ident, struct_ident, - struct_generics: struct_generics.generics, + struct_generics, entries, }) } diff --git a/crates/cgp-macro-core/src/types/delegate_component/value/mod.rs b/crates/cgp-macro-core/src/types/delegate_component/value/mod.rs new file mode 100644 index 00000000..64759aae --- /dev/null +++ b/crates/cgp-macro-core/src/types/delegate_component/value/mod.rs @@ -0,0 +1,5 @@ +mod combined; +mod inner_entries; + +pub use combined::*; +pub use inner_entries::*; From c4903ae0a956e2be2dd7055f41f075e56ee9f6e9 Mon Sep 17 00:00:00 2001 From: Soares Chen Date: Sat, 23 May 2026 16:21:17 +0200 Subject: [PATCH 37/81] Implement EvalDelegateValue --- .../types/delegate_component/value/combined.rs | 11 ++++++++++- .../src/types/delegate_component/value/eval.rs | 5 +++++ .../delegate_component/value/inner_entries.rs | 15 +++++++++++++-- .../src/types/delegate_component/value/mod.rs | 2 ++ 4 files changed, 30 insertions(+), 3 deletions(-) create mode 100644 crates/cgp-macro-core/src/types/delegate_component/value/eval.rs diff --git a/crates/cgp-macro-core/src/types/delegate_component/value/combined.rs b/crates/cgp-macro-core/src/types/delegate_component/value/combined.rs index 51c7c9c8..e8f2abba 100644 --- a/crates/cgp-macro-core/src/types/delegate_component/value/combined.rs +++ b/crates/cgp-macro-core/src/types/delegate_component/value/combined.rs @@ -2,7 +2,7 @@ use syn::Type; use syn::parse::discouraged::Speculative; use syn::parse::{Parse, ParseStream}; -use crate::types::delegate_component::DelegateValueWithInnerEntries; +use crate::types::delegate_component::{DelegateValueWithInnerEntries, EvalDelegateValue}; pub enum DelegateValue { Type(Type), @@ -22,3 +22,12 @@ impl Parse for DelegateValue { Ok(Self::Type(ty)) } } + +impl EvalDelegateValue for DelegateValue { + fn eval(&self) -> syn::Result { + match self { + Self::Type(ty) => Ok(ty.clone()), + Self::WithInner(value) => value.eval(), + } + } +} diff --git a/crates/cgp-macro-core/src/types/delegate_component/value/eval.rs b/crates/cgp-macro-core/src/types/delegate_component/value/eval.rs new file mode 100644 index 00000000..77accf66 --- /dev/null +++ b/crates/cgp-macro-core/src/types/delegate_component/value/eval.rs @@ -0,0 +1,5 @@ +use syn::Type; + +pub trait EvalDelegateValue { + fn eval(&self) -> syn::Result; +} diff --git a/crates/cgp-macro-core/src/types/delegate_component/value/inner_entries.rs b/crates/cgp-macro-core/src/types/delegate_component/value/inner_entries.rs index 6a4df32c..fe2c5299 100644 --- a/crates/cgp-macro-core/src/types/delegate_component/value/inner_entries.rs +++ b/crates/cgp-macro-core/src/types/delegate_component/value/inner_entries.rs @@ -1,9 +1,9 @@ use syn::parse::{Parse, ParseStream}; use syn::punctuated::Punctuated; use syn::token::{Comma, Gt, Lt}; -use syn::{Error, Ident, braced}; +use syn::{Error, Ident, Type, braced, parse_quote}; -use crate::types::delegate_component::DelegateEntry; +use crate::types::delegate_component::{DelegateEntry, EvalDelegateValue}; use crate::types::generics::TypeGenerics; pub struct DelegateValueWithInnerEntries { @@ -46,3 +46,14 @@ impl Parse for DelegateValueWithInnerEntries { }) } } + +impl EvalDelegateValue for DelegateValueWithInnerEntries { + fn eval(&self) -> syn::Result { + let wrapper_ident = &self.wrapper_ident; + let struct_ident = &self.struct_ident; + let struct_generics = &self.struct_generics; + + let ty = parse_quote!( #wrapper_ident < #struct_ident #struct_generics > ); + Ok(ty) + } +} diff --git a/crates/cgp-macro-core/src/types/delegate_component/value/mod.rs b/crates/cgp-macro-core/src/types/delegate_component/value/mod.rs index 64759aae..af997959 100644 --- a/crates/cgp-macro-core/src/types/delegate_component/value/mod.rs +++ b/crates/cgp-macro-core/src/types/delegate_component/value/mod.rs @@ -1,5 +1,7 @@ mod combined; +mod eval; mod inner_entries; pub use combined::*; +pub use eval::*; pub use inner_entries::*; From e7cd6edd70375342423dc4e66ee5894c38cdfdc6 Mon Sep 17 00:00:00 2001 From: Soares Chen Date: Sat, 23 May 2026 16:38:40 +0200 Subject: [PATCH 38/81] Implement EvalDelegateEntry for Normal and DirectDelegateEntry --- .../types/delegate_component/entry/direct.rs | 42 ++++++++++++++++++- .../types/delegate_component/entry/normal.rs | 16 ++++--- 2 files changed, 52 insertions(+), 6 deletions(-) diff --git a/crates/cgp-macro-core/src/types/delegate_component/entry/direct.rs b/crates/cgp-macro-core/src/types/delegate_component/entry/direct.rs index c41c9afd..aa9e1be6 100644 --- a/crates/cgp-macro-core/src/types/delegate_component/entry/direct.rs +++ b/crates/cgp-macro-core/src/types/delegate_component/entry/direct.rs @@ -1,9 +1,49 @@ use syn::token::RArrow; +use syn::{Type, parse_quote}; -use crate::types::delegate_component::{DelegateKey, DelegateValue}; +use crate::types::delegate_component::{ + DelegateKey, DelegateValue, EvalDelegateEntry, EvalDelegateKey, EvalDelegateValue, + EvaluatedDelegateEntry, +}; pub struct DirectDelegateEntry { pub key: DelegateKey, pub arrow: RArrow, pub value: DelegateValue, } + +impl EvalDelegateEntry for DirectDelegateEntry { + fn eval(&self, _context_type: &Type) -> syn::Result> { + let keys = self.key.eval()?; + let value_type = self.value.eval()?; + + let entries = keys + .into_iter() + .map(|key| { + let key_type = key.key; + let mut generics = key.generics; + + let where_predicate = parse_quote! { + #value_type: DelegateComponent< #key_type > + }; + + generics + .make_where_clause() + .predicates + .push(where_predicate); + + let direct_value_type = parse_quote! { + < #value_type as DelegateComponent< #key_type > >::Delegate + }; + + EvaluatedDelegateEntry { + generics, + key: key_type, + value: direct_value_type, + } + }) + .collect(); + + Ok(entries) + } +} diff --git a/crates/cgp-macro-core/src/types/delegate_component/entry/normal.rs b/crates/cgp-macro-core/src/types/delegate_component/entry/normal.rs index d3e1877a..e64ba330 100644 --- a/crates/cgp-macro-core/src/types/delegate_component/entry/normal.rs +++ b/crates/cgp-macro-core/src/types/delegate_component/entry/normal.rs @@ -2,7 +2,8 @@ use syn::Type; use syn::token::Colon; use crate::types::delegate_component::{ - DelegateKey, DelegateValue, EvalDelegateEntry, EvalDelegateKey, EvaluatedDelegateEntry, + DelegateKey, DelegateValue, EvalDelegateEntry, EvalDelegateKey, EvalDelegateValue, + EvaluatedDelegateEntry, }; pub struct NormalDelegateEntry { @@ -14,11 +15,16 @@ pub struct NormalDelegateEntry { impl EvalDelegateEntry for NormalDelegateEntry { fn eval(&self, _context_type: &Type) -> syn::Result> { let keys = self.key.eval()?; - let entries = Vec::new(); + let value_type = self.value.eval()?; - for _key in keys { - todo!() - } + let entries = keys + .into_iter() + .map(|key| EvaluatedDelegateEntry { + generics: key.generics, + key: key.key, + value: value_type.clone(), + }) + .collect(); Ok(entries) } From 6ab17e4a6acdba136cee32bdffd4372b8f6224db Mon Sep 17 00:00:00 2001 From: Soares Chen Date: Sat, 23 May 2026 16:49:15 +0200 Subject: [PATCH 39/81] Add namespace variant to DelegateEntry --- crates/cgp-macro-core/src/exports.rs | 1 + crates/cgp-macro-core/src/macros.rs | 8 ++-- crates/cgp-macro-core/src/traits/keyword.rs | 10 ++--- .../delegate_component/entry/combined.rs | 43 +++++++++++++++---- .../types/delegate_component/entry/direct.rs | 5 ++- .../delegate_component/entry/namespace.rs | 5 ++- .../types/delegate_component/entry/open.rs | 5 ++- 7 files changed, 51 insertions(+), 26 deletions(-) diff --git a/crates/cgp-macro-core/src/exports.rs b/crates/cgp-macro-core/src/exports.rs index 8e0eb332..27d0b0f4 100644 --- a/crates/cgp-macro-core/src/exports.rs +++ b/crates/cgp-macro-core/src/exports.rs @@ -7,4 +7,5 @@ export_constructs! { Symbol, PathCons, RedirectLookup, + DelegateComponent, } diff --git a/crates/cgp-macro-core/src/macros.rs b/crates/cgp-macro-core/src/macros.rs index 4edeed81..330613a8 100644 --- a/crates/cgp-macro-core/src/macros.rs +++ b/crates/cgp-macro-core/src/macros.rs @@ -23,13 +23,11 @@ macro_rules! export_constructs { #[macro_export] macro_rules! define_keyword { - ( $struct_ident:ident, $impl_ident:ident, $value:literal ) => { - pub struct $impl_ident; + ( $struct_ident:ident, $value:literal ) => { + pub struct $struct_ident; - impl $crate::traits::IsKeyword for $impl_ident { + impl $crate::traits::IsKeyword for $struct_ident { const IDENT: &'static str = "open"; } - - pub type $struct_ident = $crate::types::keyword::Keyword<$impl_ident>; }; } diff --git a/crates/cgp-macro-core/src/traits/keyword.rs b/crates/cgp-macro-core/src/traits/keyword.rs index fc76588f..125c7937 100644 --- a/crates/cgp-macro-core/src/traits/keyword.rs +++ b/crates/cgp-macro-core/src/traits/keyword.rs @@ -1,18 +1,16 @@ use syn::Ident; use syn::parse::ParseBuffer; -use crate::types::keyword::Keyword; - pub trait IsKeyword { const IDENT: &'static str; } -pub trait PeekKeyword { - fn peek(&self, keyword: K) -> bool; +pub trait PeekKeyword { + fn peek_keyword(&self) -> bool; } -impl<'a, K: IsKeyword> PeekKeyword> for ParseBuffer<'a> { - fn peek(&self, _keyword: Keyword) -> bool { +impl<'a> PeekKeyword for ParseBuffer<'a> { + fn peek_keyword(&self) -> bool { if let Ok(ident) = self.fork().parse::() && ident == K::IDENT { diff --git a/crates/cgp-macro-core/src/types/delegate_component/entry/combined.rs b/crates/cgp-macro-core/src/types/delegate_component/entry/combined.rs index 8ecbb70e..e4ee1d8d 100644 --- a/crates/cgp-macro-core/src/types/delegate_component/entry/combined.rs +++ b/crates/cgp-macro-core/src/types/delegate_component/entry/combined.rs @@ -1,23 +1,48 @@ +use syn::Type; use syn::parse::{Parse, ParseStream}; -use crate::types::delegate_component::{DelegateMode, DirectDelegateEntry, NormalDelegateEntry}; +use crate::traits::PeekKeyword; +use crate::types::delegate_component::{ + DelegateMode, DirectDelegateEntry, EvalDelegateEntry, EvaluatedDelegateEntry, Namespace, + NamespaceDelegateEntry, NormalDelegateEntry, +}; pub enum DelegateEntry { Normal(NormalDelegateEntry), Direct(DirectDelegateEntry), + Namespace(NamespaceDelegateEntry), } impl Parse for DelegateEntry { fn parse(input: ParseStream) -> syn::Result { - let key = input.parse()?; - let mode: DelegateMode = input.parse()?; - let value = input.parse()?; + if input.peek_keyword::() { + let namespace_entry = input.parse()?; + Ok(Self::Namespace(namespace_entry)) + } else { + let key = input.parse()?; + let mode: DelegateMode = input.parse()?; + let value = input.parse()?; - let entry = match mode { - DelegateMode::Normal(colon) => Self::Normal(NormalDelegateEntry { key, colon, value }), - DelegateMode::Direct(arrow) => Self::Direct(DirectDelegateEntry { key, arrow, value }), - }; + let entry = match mode { + DelegateMode::Normal(colon) => { + Self::Normal(NormalDelegateEntry { key, colon, value }) + } + DelegateMode::Direct(arrow) => { + Self::Direct(DirectDelegateEntry { key, arrow, value }) + } + }; - Ok(entry) + Ok(entry) + } + } +} + +impl EvalDelegateEntry for DelegateEntry { + fn eval(&self, context_type: &Type) -> syn::Result> { + match self { + Self::Normal(entry) => entry.eval(context_type), + Self::Direct(entry) => entry.eval(context_type), + Self::Namespace(entry) => entry.eval(context_type), + } } } diff --git a/crates/cgp-macro-core/src/types/delegate_component/entry/direct.rs b/crates/cgp-macro-core/src/types/delegate_component/entry/direct.rs index aa9e1be6..e67373ba 100644 --- a/crates/cgp-macro-core/src/types/delegate_component/entry/direct.rs +++ b/crates/cgp-macro-core/src/types/delegate_component/entry/direct.rs @@ -1,6 +1,7 @@ use syn::token::RArrow; use syn::{Type, parse_quote}; +use crate::exports::DelegateComponent; use crate::types::delegate_component::{ DelegateKey, DelegateValue, EvalDelegateEntry, EvalDelegateKey, EvalDelegateValue, EvaluatedDelegateEntry, @@ -24,7 +25,7 @@ impl EvalDelegateEntry for DirectDelegateEntry { let mut generics = key.generics; let where_predicate = parse_quote! { - #value_type: DelegateComponent< #key_type > + #value_type: #DelegateComponent< #key_type > }; generics @@ -33,7 +34,7 @@ impl EvalDelegateEntry for DirectDelegateEntry { .push(where_predicate); let direct_value_type = parse_quote! { - < #value_type as DelegateComponent< #key_type > >::Delegate + < #value_type as #DelegateComponent< #key_type > >::Delegate }; EvaluatedDelegateEntry { diff --git a/crates/cgp-macro-core/src/types/delegate_component/entry/namespace.rs b/crates/cgp-macro-core/src/types/delegate_component/entry/namespace.rs index 329e5ede..cbb9821b 100644 --- a/crates/cgp-macro-core/src/types/delegate_component/entry/namespace.rs +++ b/crates/cgp-macro-core/src/types/delegate_component/entry/namespace.rs @@ -4,11 +4,12 @@ use syn::{Ident, Type, parse_quote}; use crate::define_keyword; use crate::types::delegate_component::{EvalDelegateEntry, EvaluatedDelegateEntry}; +use crate::types::keyword::Keyword; -define_keyword!(Namespace, NamespaceKeyword, "namespace"); +define_keyword!(Namespace, "namespace"); pub struct NamespaceDelegateEntry { - pub namespace: Namespace, + pub namespace: Keyword, pub ident: Ident, pub semi: Semi, } diff --git a/crates/cgp-macro-core/src/types/delegate_component/entry/open.rs b/crates/cgp-macro-core/src/types/delegate_component/entry/open.rs index 154afd7f..02ee4d41 100644 --- a/crates/cgp-macro-core/src/types/delegate_component/entry/open.rs +++ b/crates/cgp-macro-core/src/types/delegate_component/entry/open.rs @@ -6,11 +6,12 @@ use syn::{Type, parse_quote}; use crate::define_keyword; use crate::exports::{Nil, PathCons, RedirectLookup}; use crate::types::delegate_component::{EvalDelegateEntry, EvaluatedDelegateEntry}; +use crate::types::keyword::Keyword; -define_keyword!(Open, OpenKeyword, "open"); +define_keyword!(Open, "open"); pub struct OpenDelegateEntry { - pub open: Open, + pub open: Keyword, pub components: Punctuated, pub semi: Semi, } From 84cfa6391638f50ae866ae9631b7b38c5c3380f2 Mon Sep 17 00:00:00 2001 From: Soares Chen Date: Sat, 23 May 2026 16:51:17 +0200 Subject: [PATCH 40/81] Add open variant to DelegateEntry --- .../src/types/delegate_component/entry/combined.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/crates/cgp-macro-core/src/types/delegate_component/entry/combined.rs b/crates/cgp-macro-core/src/types/delegate_component/entry/combined.rs index e4ee1d8d..db800cf2 100644 --- a/crates/cgp-macro-core/src/types/delegate_component/entry/combined.rs +++ b/crates/cgp-macro-core/src/types/delegate_component/entry/combined.rs @@ -4,13 +4,14 @@ use syn::parse::{Parse, ParseStream}; use crate::traits::PeekKeyword; use crate::types::delegate_component::{ DelegateMode, DirectDelegateEntry, EvalDelegateEntry, EvaluatedDelegateEntry, Namespace, - NamespaceDelegateEntry, NormalDelegateEntry, + NamespaceDelegateEntry, NormalDelegateEntry, Open, OpenDelegateEntry, }; pub enum DelegateEntry { Normal(NormalDelegateEntry), Direct(DirectDelegateEntry), Namespace(NamespaceDelegateEntry), + Open(OpenDelegateEntry), } impl Parse for DelegateEntry { @@ -18,6 +19,9 @@ impl Parse for DelegateEntry { if input.peek_keyword::() { let namespace_entry = input.parse()?; Ok(Self::Namespace(namespace_entry)) + } else if input.peek_keyword::() { + let open_entry = input.parse()?; + Ok(Self::Open(open_entry)) } else { let key = input.parse()?; let mode: DelegateMode = input.parse()?; @@ -43,6 +47,7 @@ impl EvalDelegateEntry for DelegateEntry { Self::Normal(entry) => entry.eval(context_type), Self::Direct(entry) => entry.eval(context_type), Self::Namespace(entry) => entry.eval(context_type), + Self::Open(entry) => entry.eval(context_type), } } } From 7cee9825a08f41bb80054fa7e8e064ab001e8761 Mon Sep 17 00:00:00 2001 From: Soares Chen Date: Sat, 23 May 2026 17:19:32 +0200 Subject: [PATCH 41/81] Derive DelegateComponent and IsProviderFor in EvaluatedDelegateEntry --- crates/cgp-macro-core/src/exports.rs | 1 + .../types/delegate_component/entry/direct.rs | 3 +- .../types/delegate_component/entry/eval.rs | 51 ++++++++++++++++++- .../delegate_component/entry/namespace.rs | 1 + .../types/delegate_component/entry/normal.rs | 3 +- .../types/delegate_component/entry/open.rs | 1 + 6 files changed, 57 insertions(+), 3 deletions(-) diff --git a/crates/cgp-macro-core/src/exports.rs b/crates/cgp-macro-core/src/exports.rs index 27d0b0f4..36841735 100644 --- a/crates/cgp-macro-core/src/exports.rs +++ b/crates/cgp-macro-core/src/exports.rs @@ -8,4 +8,5 @@ export_constructs! { PathCons, RedirectLookup, DelegateComponent, + IsProviderFor, } diff --git a/crates/cgp-macro-core/src/types/delegate_component/entry/direct.rs b/crates/cgp-macro-core/src/types/delegate_component/entry/direct.rs index e67373ba..3f7dcdcf 100644 --- a/crates/cgp-macro-core/src/types/delegate_component/entry/direct.rs +++ b/crates/cgp-macro-core/src/types/delegate_component/entry/direct.rs @@ -14,7 +14,7 @@ pub struct DirectDelegateEntry { } impl EvalDelegateEntry for DirectDelegateEntry { - fn eval(&self, _context_type: &Type) -> syn::Result> { + fn eval(&self, context_type: &Type) -> syn::Result> { let keys = self.key.eval()?; let value_type = self.value.eval()?; @@ -38,6 +38,7 @@ impl EvalDelegateEntry for DirectDelegateEntry { }; EvaluatedDelegateEntry { + table_type: context_type.clone(), generics, key: key_type, value: direct_value_type, diff --git a/crates/cgp-macro-core/src/types/delegate_component/entry/eval.rs b/crates/cgp-macro-core/src/types/delegate_component/entry/eval.rs index 5656a862..556d88bd 100644 --- a/crates/cgp-macro-core/src/types/delegate_component/entry/eval.rs +++ b/crates/cgp-macro-core/src/types/delegate_component/entry/eval.rs @@ -1,6 +1,10 @@ -use syn::{Generics, Type}; +use quote::quote; +use syn::{Generics, ItemImpl, Type, parse_quote, parse2}; + +use crate::exports::{DelegateComponent, IsProviderFor}; pub struct EvaluatedDelegateEntry { + pub table_type: Type, pub generics: Generics, pub key: Type, pub value: Type, @@ -9,3 +13,48 @@ pub struct EvaluatedDelegateEntry { pub trait EvalDelegateEntry { fn eval(&self, context_type: &Type) -> syn::Result>; } + +impl EvaluatedDelegateEntry { + pub fn to_delegate_component_impl(&self) -> syn::Result { + let table_type = &self.table_type; + let generics = &self.generics; + let key = &self.key; + let value = &self.value; + + let (impl_generics, _, where_clause) = generics.split_for_impl(); + + parse2(quote! { + impl #impl_generics + #DelegateComponent< #key > + for #table_type + #where_clause + { + type Delegate = #value; + } + }) + } + + pub fn to_is_provider_for_impl(&self) -> syn::Result { + let table_type = &self.table_type; + let mut generics = self.generics.clone(); + let key = &self.key; + let value = &self.value; + + generics.params.push(parse_quote!(__Context__)); + generics.params.push(parse_quote!(__Params__)); + + generics.make_where_clause().predicates.push(parse_quote! { + #value: #IsProviderFor<#key, __Context__, __Params__>, + }); + + let (impl_generics, _, where_clause) = generics.split_for_impl(); + + parse2(quote! { + impl #impl_generics + #IsProviderFor< #key, __Context__, __Params__ > + for #table_type + #where_clause + {} + }) + } +} diff --git a/crates/cgp-macro-core/src/types/delegate_component/entry/namespace.rs b/crates/cgp-macro-core/src/types/delegate_component/entry/namespace.rs index cbb9821b..97adc997 100644 --- a/crates/cgp-macro-core/src/types/delegate_component/entry/namespace.rs +++ b/crates/cgp-macro-core/src/types/delegate_component/entry/namespace.rs @@ -46,6 +46,7 @@ impl EvalDelegateEntry for NamespaceDelegateEntry { }; let entry = EvaluatedDelegateEntry { + table_type: context_type.clone(), generics, key, value, diff --git a/crates/cgp-macro-core/src/types/delegate_component/entry/normal.rs b/crates/cgp-macro-core/src/types/delegate_component/entry/normal.rs index e64ba330..384d22b5 100644 --- a/crates/cgp-macro-core/src/types/delegate_component/entry/normal.rs +++ b/crates/cgp-macro-core/src/types/delegate_component/entry/normal.rs @@ -13,13 +13,14 @@ pub struct NormalDelegateEntry { } impl EvalDelegateEntry for NormalDelegateEntry { - fn eval(&self, _context_type: &Type) -> syn::Result> { + fn eval(&self, context_type: &Type) -> syn::Result> { let keys = self.key.eval()?; let value_type = self.value.eval()?; let entries = keys .into_iter() .map(|key| EvaluatedDelegateEntry { + table_type: context_type.clone(), generics: key.generics, key: key.key, value: value_type.clone(), diff --git a/crates/cgp-macro-core/src/types/delegate_component/entry/open.rs b/crates/cgp-macro-core/src/types/delegate_component/entry/open.rs index 02ee4d41..f866237a 100644 --- a/crates/cgp-macro-core/src/types/delegate_component/entry/open.rs +++ b/crates/cgp-macro-core/src/types/delegate_component/entry/open.rs @@ -46,6 +46,7 @@ impl EvalDelegateEntry for OpenDelegateEntry { let key = component.clone(); entries.push(EvaluatedDelegateEntry { + table_type: context_type.clone(), generics: Default::default(), key, value, From ff6d856bbd99c3cc73f9838f1c8c31424430408b Mon Sep 17 00:00:00 2001 From: Soares Chen Date: Sat, 23 May 2026 17:29:46 +0200 Subject: [PATCH 42/81] Rename context_type to table_type in EvalDelegateEntry --- .../src/types/delegate_component/entry/combined.rs | 10 +++++----- .../src/types/delegate_component/entry/direct.rs | 4 ++-- .../src/types/delegate_component/entry/eval.rs | 2 +- .../src/types/delegate_component/entry/namespace.rs | 12 ++++++------ .../src/types/delegate_component/entry/normal.rs | 4 ++-- .../src/types/delegate_component/entry/open.rs | 6 +++--- 6 files changed, 19 insertions(+), 19 deletions(-) diff --git a/crates/cgp-macro-core/src/types/delegate_component/entry/combined.rs b/crates/cgp-macro-core/src/types/delegate_component/entry/combined.rs index db800cf2..8175d7bb 100644 --- a/crates/cgp-macro-core/src/types/delegate_component/entry/combined.rs +++ b/crates/cgp-macro-core/src/types/delegate_component/entry/combined.rs @@ -42,12 +42,12 @@ impl Parse for DelegateEntry { } impl EvalDelegateEntry for DelegateEntry { - fn eval(&self, context_type: &Type) -> syn::Result> { + fn eval(&self, table_type: &Type) -> syn::Result> { match self { - Self::Normal(entry) => entry.eval(context_type), - Self::Direct(entry) => entry.eval(context_type), - Self::Namespace(entry) => entry.eval(context_type), - Self::Open(entry) => entry.eval(context_type), + Self::Normal(entry) => entry.eval(table_type), + Self::Direct(entry) => entry.eval(table_type), + Self::Namespace(entry) => entry.eval(table_type), + Self::Open(entry) => entry.eval(table_type), } } } diff --git a/crates/cgp-macro-core/src/types/delegate_component/entry/direct.rs b/crates/cgp-macro-core/src/types/delegate_component/entry/direct.rs index 3f7dcdcf..3b5a365f 100644 --- a/crates/cgp-macro-core/src/types/delegate_component/entry/direct.rs +++ b/crates/cgp-macro-core/src/types/delegate_component/entry/direct.rs @@ -14,7 +14,7 @@ pub struct DirectDelegateEntry { } impl EvalDelegateEntry for DirectDelegateEntry { - fn eval(&self, context_type: &Type) -> syn::Result> { + fn eval(&self, table_type: &Type) -> syn::Result> { let keys = self.key.eval()?; let value_type = self.value.eval()?; @@ -38,7 +38,7 @@ impl EvalDelegateEntry for DirectDelegateEntry { }; EvaluatedDelegateEntry { - table_type: context_type.clone(), + table_type: table_type.clone(), generics, key: key_type, value: direct_value_type, diff --git a/crates/cgp-macro-core/src/types/delegate_component/entry/eval.rs b/crates/cgp-macro-core/src/types/delegate_component/entry/eval.rs index 556d88bd..869a0cd0 100644 --- a/crates/cgp-macro-core/src/types/delegate_component/entry/eval.rs +++ b/crates/cgp-macro-core/src/types/delegate_component/entry/eval.rs @@ -11,7 +11,7 @@ pub struct EvaluatedDelegateEntry { } pub trait EvalDelegateEntry { - fn eval(&self, context_type: &Type) -> syn::Result>; + fn eval(&self, table_type: &Type) -> syn::Result>; } impl EvaluatedDelegateEntry { diff --git a/crates/cgp-macro-core/src/types/delegate_component/entry/namespace.rs b/crates/cgp-macro-core/src/types/delegate_component/entry/namespace.rs index 97adc997..d13c6b76 100644 --- a/crates/cgp-macro-core/src/types/delegate_component/entry/namespace.rs +++ b/crates/cgp-macro-core/src/types/delegate_component/entry/namespace.rs @@ -1,4 +1,4 @@ -use syn::parse::Parse; +use syn::parse::{Parse, ParseStream}; use syn::token::Semi; use syn::{Ident, Type, parse_quote}; @@ -15,7 +15,7 @@ pub struct NamespaceDelegateEntry { } impl Parse for NamespaceDelegateEntry { - fn parse(input: syn::parse::ParseStream) -> syn::Result { + fn parse(input: ParseStream) -> syn::Result { let namespace = input.parse()?; let ident = input.parse()?; let semi = input.parse()?; @@ -29,7 +29,7 @@ impl Parse for NamespaceDelegateEntry { } impl EvalDelegateEntry for NamespaceDelegateEntry { - fn eval(&self, context_type: &Type) -> syn::Result> { + fn eval(&self, table_type: &Type) -> syn::Result> { let namespace_ident = if &self.ident == "default" { Ident::new("DefaultNamespace", self.ident.span()) } else { @@ -38,15 +38,15 @@ impl EvalDelegateEntry for NamespaceDelegateEntry { let key = parse_quote!(__Component__); let generics = parse_quote! { - <__Component__: #namespace_ident< #context_type >> + <__Component__: #namespace_ident< #table_type >> }; let value = parse_quote! { - < __Component__ as #namespace_ident< #context_type >>::Provider + < __Component__ as #namespace_ident< #table_type >>::Provider }; let entry = EvaluatedDelegateEntry { - table_type: context_type.clone(), + table_type: table_type.clone(), generics, key, value, diff --git a/crates/cgp-macro-core/src/types/delegate_component/entry/normal.rs b/crates/cgp-macro-core/src/types/delegate_component/entry/normal.rs index 384d22b5..18d09af4 100644 --- a/crates/cgp-macro-core/src/types/delegate_component/entry/normal.rs +++ b/crates/cgp-macro-core/src/types/delegate_component/entry/normal.rs @@ -13,14 +13,14 @@ pub struct NormalDelegateEntry { } impl EvalDelegateEntry for NormalDelegateEntry { - fn eval(&self, context_type: &Type) -> syn::Result> { + fn eval(&self, table_type: &Type) -> syn::Result> { let keys = self.key.eval()?; let value_type = self.value.eval()?; let entries = keys .into_iter() .map(|key| EvaluatedDelegateEntry { - table_type: context_type.clone(), + table_type: table_type.clone(), generics: key.generics, key: key.key, value: value_type.clone(), diff --git a/crates/cgp-macro-core/src/types/delegate_component/entry/open.rs b/crates/cgp-macro-core/src/types/delegate_component/entry/open.rs index f866237a..96cc0677 100644 --- a/crates/cgp-macro-core/src/types/delegate_component/entry/open.rs +++ b/crates/cgp-macro-core/src/types/delegate_component/entry/open.rs @@ -32,13 +32,13 @@ impl Parse for OpenDelegateEntry { } impl EvalDelegateEntry for OpenDelegateEntry { - fn eval(&self, context_type: &Type) -> syn::Result> { + fn eval(&self, table_type: &Type) -> syn::Result> { let mut entries = Vec::new(); for component in &self.components { let value: Type = parse_quote! { #RedirectLookup< - #context_type, + #table_type, #PathCons<#component, #Nil>, > }; @@ -46,7 +46,7 @@ impl EvalDelegateEntry for OpenDelegateEntry { let key = component.clone(); entries.push(EvaluatedDelegateEntry { - table_type: context_type.clone(), + table_type: table_type.clone(), generics: Default::default(), key, value, From 78b299e5e36007d97b1cd5f94374d70b2b01cc2f Mon Sep 17 00:00:00 2001 From: Soares Chen Date: Sat, 23 May 2026 17:50:54 +0200 Subject: [PATCH 43/81] Implement DelegateTable --- .../src/types/delegate_component/mod.rs | 2 + .../src/types/delegate_component/table.rs | 34 +++++++++++ .../delegate_component/value/combined.rs | 10 ++-- .../delegate_component/value/inner_entries.rs | 59 ------------------- .../delegate_component/value/inner_table.rs | 44 ++++++++++++++ .../src/types/delegate_component/value/mod.rs | 4 +- 6 files changed, 87 insertions(+), 66 deletions(-) create mode 100644 crates/cgp-macro-core/src/types/delegate_component/table.rs delete mode 100644 crates/cgp-macro-core/src/types/delegate_component/value/inner_entries.rs create mode 100644 crates/cgp-macro-core/src/types/delegate_component/value/inner_table.rs diff --git a/crates/cgp-macro-core/src/types/delegate_component/mod.rs b/crates/cgp-macro-core/src/types/delegate_component/mod.rs index bd3b5256..ccf2c51e 100644 --- a/crates/cgp-macro-core/src/types/delegate_component/mod.rs +++ b/crates/cgp-macro-core/src/types/delegate_component/mod.rs @@ -1,7 +1,9 @@ mod entry; mod key; +mod table; mod value; pub use entry::*; pub use key::*; +pub use table::*; pub use value::*; diff --git a/crates/cgp-macro-core/src/types/delegate_component/table.rs b/crates/cgp-macro-core/src/types/delegate_component/table.rs new file mode 100644 index 00000000..2183b48c --- /dev/null +++ b/crates/cgp-macro-core/src/types/delegate_component/table.rs @@ -0,0 +1,34 @@ +use syn::parse::{Parse, ParseStream}; +use syn::punctuated::Punctuated; +use syn::token::Comma; +use syn::{Ident, braced}; + +use crate::types::delegate_component::DelegateEntry; +use crate::types::generics::TypeGenerics; + +pub struct DelegateTable { + pub table_ident: Ident, + pub table_generics: TypeGenerics, + pub entries: Punctuated, +} + +impl Parse for DelegateTable { + fn parse(input: ParseStream) -> syn::Result { + let table_ident = input.parse()?; + + let table_generics: TypeGenerics = input.parse()?; + + let entries = { + let content; + braced!(content in input); + + Punctuated::parse_terminated(&content)? + }; + + Ok(Self { + table_ident, + table_generics, + entries, + }) + } +} diff --git a/crates/cgp-macro-core/src/types/delegate_component/value/combined.rs b/crates/cgp-macro-core/src/types/delegate_component/value/combined.rs index e8f2abba..274fa3a4 100644 --- a/crates/cgp-macro-core/src/types/delegate_component/value/combined.rs +++ b/crates/cgp-macro-core/src/types/delegate_component/value/combined.rs @@ -2,20 +2,20 @@ use syn::Type; use syn::parse::discouraged::Speculative; use syn::parse::{Parse, ParseStream}; -use crate::types::delegate_component::{DelegateValueWithInnerEntries, EvalDelegateValue}; +use crate::types::delegate_component::{DelegateValueWithInnerTable, EvalDelegateValue}; pub enum DelegateValue { Type(Type), - WithInner(DelegateValueWithInnerEntries), + WithTable(DelegateValueWithInnerTable), } impl Parse for DelegateValue { fn parse(input: ParseStream) -> syn::Result { let fork = input.fork(); - if let Ok(value) = fork.parse::() { + if let Ok(value) = fork.parse::() { input.advance_to(&fork); - return Ok(Self::WithInner(value)); + return Ok(Self::WithTable(value)); } let ty: Type = input.parse()?; @@ -27,7 +27,7 @@ impl EvalDelegateValue for DelegateValue { fn eval(&self) -> syn::Result { match self { Self::Type(ty) => Ok(ty.clone()), - Self::WithInner(value) => value.eval(), + Self::WithTable(value) => value.eval(), } } } diff --git a/crates/cgp-macro-core/src/types/delegate_component/value/inner_entries.rs b/crates/cgp-macro-core/src/types/delegate_component/value/inner_entries.rs deleted file mode 100644 index fe2c5299..00000000 --- a/crates/cgp-macro-core/src/types/delegate_component/value/inner_entries.rs +++ /dev/null @@ -1,59 +0,0 @@ -use syn::parse::{Parse, ParseStream}; -use syn::punctuated::Punctuated; -use syn::token::{Comma, Gt, Lt}; -use syn::{Error, Ident, Type, braced, parse_quote}; - -use crate::types::delegate_component::{DelegateEntry, EvalDelegateValue}; -use crate::types::generics::TypeGenerics; - -pub struct DelegateValueWithInnerEntries { - pub wrapper_ident: Ident, - pub struct_ident: Ident, - pub struct_generics: TypeGenerics, - pub entries: Punctuated, -} - -impl Parse for DelegateValueWithInnerEntries { - fn parse(input: ParseStream) -> syn::Result { - let wrapper_ident = input.parse()?; - - let _: Lt = input.parse()?; - - let new_ident: Ident = input.parse()?; - - if new_ident != "new" { - return Err(Error::new(new_ident.span(), "expect `new` keyword")); - } - - let struct_ident = input.parse()?; - - let struct_generics: TypeGenerics = input.parse()?; - - let entries = { - let content; - braced!(content in input); - - Punctuated::parse_terminated(&content)? - }; - - let _: Gt = input.parse()?; - - Ok(Self { - wrapper_ident, - struct_ident, - struct_generics, - entries, - }) - } -} - -impl EvalDelegateValue for DelegateValueWithInnerEntries { - fn eval(&self) -> syn::Result { - let wrapper_ident = &self.wrapper_ident; - let struct_ident = &self.struct_ident; - let struct_generics = &self.struct_generics; - - let ty = parse_quote!( #wrapper_ident < #struct_ident #struct_generics > ); - Ok(ty) - } -} diff --git a/crates/cgp-macro-core/src/types/delegate_component/value/inner_table.rs b/crates/cgp-macro-core/src/types/delegate_component/value/inner_table.rs new file mode 100644 index 00000000..ea29f721 --- /dev/null +++ b/crates/cgp-macro-core/src/types/delegate_component/value/inner_table.rs @@ -0,0 +1,44 @@ +use syn::parse::{Parse, ParseStream}; +use syn::token::{Gt, Lt}; +use syn::{Error, Ident, Type, parse_quote}; + +use crate::types::delegate_component::{DelegateTable, EvalDelegateValue}; + +pub struct DelegateValueWithInnerTable { + pub wrapper_ident: Ident, + pub inner_table: DelegateTable, +} + +impl Parse for DelegateValueWithInnerTable { + fn parse(input: ParseStream) -> syn::Result { + let wrapper_ident = input.parse()?; + + let _: Lt = input.parse()?; + + let new_ident: Ident = input.parse()?; + + if new_ident != "new" { + return Err(Error::new(new_ident.span(), "expect `new` keyword")); + } + + let inner_table = input.parse()?; + + let _: Gt = input.parse()?; + + Ok(Self { + wrapper_ident, + inner_table, + }) + } +} + +impl EvalDelegateValue for DelegateValueWithInnerTable { + fn eval(&self) -> syn::Result { + let wrapper_ident = &self.wrapper_ident; + let struct_ident = &self.inner_table.table_ident; + let struct_generics = &self.inner_table.table_generics; + + let ty = parse_quote!( #wrapper_ident < #struct_ident #struct_generics > ); + Ok(ty) + } +} diff --git a/crates/cgp-macro-core/src/types/delegate_component/value/mod.rs b/crates/cgp-macro-core/src/types/delegate_component/value/mod.rs index af997959..27b36a52 100644 --- a/crates/cgp-macro-core/src/types/delegate_component/value/mod.rs +++ b/crates/cgp-macro-core/src/types/delegate_component/value/mod.rs @@ -1,7 +1,7 @@ mod combined; mod eval; -mod inner_entries; +mod inner_table; pub use combined::*; pub use eval::*; -pub use inner_entries::*; +pub use inner_table::*; From 308d0ce55cec12a56917d4f07ef2e2732f1c22e2 Mon Sep 17 00:00:00 2001 From: Soares Chen Date: Sat, 23 May 2026 17:54:55 +0200 Subject: [PATCH 44/81] Add `new` keyword --- .../src/types/delegate_component/entry/combined.rs | 5 +++-- .../src/types/delegate_component/entry/namespace.rs | 4 +--- .../src/types/delegate_component/entry/open.rs | 4 +--- .../types/delegate_component/value/inner_table.rs | 12 ++++++------ crates/cgp-macro-core/src/types/keywords.rs | 7 +++++++ crates/cgp-macro-core/src/types/mod.rs | 1 + 6 files changed, 19 insertions(+), 14 deletions(-) create mode 100644 crates/cgp-macro-core/src/types/keywords.rs diff --git a/crates/cgp-macro-core/src/types/delegate_component/entry/combined.rs b/crates/cgp-macro-core/src/types/delegate_component/entry/combined.rs index 8175d7bb..64db7664 100644 --- a/crates/cgp-macro-core/src/types/delegate_component/entry/combined.rs +++ b/crates/cgp-macro-core/src/types/delegate_component/entry/combined.rs @@ -3,9 +3,10 @@ use syn::parse::{Parse, ParseStream}; use crate::traits::PeekKeyword; use crate::types::delegate_component::{ - DelegateMode, DirectDelegateEntry, EvalDelegateEntry, EvaluatedDelegateEntry, Namespace, - NamespaceDelegateEntry, NormalDelegateEntry, Open, OpenDelegateEntry, + DelegateMode, DirectDelegateEntry, EvalDelegateEntry, EvaluatedDelegateEntry, + NamespaceDelegateEntry, NormalDelegateEntry, OpenDelegateEntry, }; +use crate::types::keywords::{Namespace, Open}; pub enum DelegateEntry { Normal(NormalDelegateEntry), diff --git a/crates/cgp-macro-core/src/types/delegate_component/entry/namespace.rs b/crates/cgp-macro-core/src/types/delegate_component/entry/namespace.rs index d13c6b76..1d1b83dc 100644 --- a/crates/cgp-macro-core/src/types/delegate_component/entry/namespace.rs +++ b/crates/cgp-macro-core/src/types/delegate_component/entry/namespace.rs @@ -2,11 +2,9 @@ use syn::parse::{Parse, ParseStream}; use syn::token::Semi; use syn::{Ident, Type, parse_quote}; -use crate::define_keyword; use crate::types::delegate_component::{EvalDelegateEntry, EvaluatedDelegateEntry}; use crate::types::keyword::Keyword; - -define_keyword!(Namespace, "namespace"); +use crate::types::keywords::Namespace; pub struct NamespaceDelegateEntry { pub namespace: Keyword, diff --git a/crates/cgp-macro-core/src/types/delegate_component/entry/open.rs b/crates/cgp-macro-core/src/types/delegate_component/entry/open.rs index 96cc0677..afcf1b38 100644 --- a/crates/cgp-macro-core/src/types/delegate_component/entry/open.rs +++ b/crates/cgp-macro-core/src/types/delegate_component/entry/open.rs @@ -3,12 +3,10 @@ use syn::punctuated::Punctuated; use syn::token::{Comma, Semi}; use syn::{Type, parse_quote}; -use crate::define_keyword; use crate::exports::{Nil, PathCons, RedirectLookup}; use crate::types::delegate_component::{EvalDelegateEntry, EvaluatedDelegateEntry}; use crate::types::keyword::Keyword; - -define_keyword!(Open, "open"); +use crate::types::keywords::Open; pub struct OpenDelegateEntry { pub open: Keyword, diff --git a/crates/cgp-macro-core/src/types/delegate_component/value/inner_table.rs b/crates/cgp-macro-core/src/types/delegate_component/value/inner_table.rs index ea29f721..4c579c73 100644 --- a/crates/cgp-macro-core/src/types/delegate_component/value/inner_table.rs +++ b/crates/cgp-macro-core/src/types/delegate_component/value/inner_table.rs @@ -1,10 +1,13 @@ use syn::parse::{Parse, ParseStream}; use syn::token::{Gt, Lt}; -use syn::{Error, Ident, Type, parse_quote}; +use syn::{Ident, Type, parse_quote}; use crate::types::delegate_component::{DelegateTable, EvalDelegateValue}; +use crate::types::keyword::Keyword; +use crate::types::keywords::New; pub struct DelegateValueWithInnerTable { + pub new: Keyword, pub wrapper_ident: Ident, pub inner_table: DelegateTable, } @@ -15,17 +18,14 @@ impl Parse for DelegateValueWithInnerTable { let _: Lt = input.parse()?; - let new_ident: Ident = input.parse()?; - - if new_ident != "new" { - return Err(Error::new(new_ident.span(), "expect `new` keyword")); - } + let new = input.parse()?; let inner_table = input.parse()?; let _: Gt = input.parse()?; Ok(Self { + new, wrapper_ident, inner_table, }) diff --git a/crates/cgp-macro-core/src/types/keywords.rs b/crates/cgp-macro-core/src/types/keywords.rs new file mode 100644 index 00000000..124f505a --- /dev/null +++ b/crates/cgp-macro-core/src/types/keywords.rs @@ -0,0 +1,7 @@ +use crate::define_keyword; + +define_keyword!(New, "new"); + +define_keyword!(Namespace, "namespace"); + +define_keyword!(Open, "open"); diff --git a/crates/cgp-macro-core/src/types/mod.rs b/crates/cgp-macro-core/src/types/mod.rs index 711091ff..0043dec2 100644 --- a/crates/cgp-macro-core/src/types/mod.rs +++ b/crates/cgp-macro-core/src/types/mod.rs @@ -1,6 +1,7 @@ pub mod delegate_component; pub mod generics; pub mod keyword; +pub mod keywords; pub mod namespace; pub mod path; pub mod symbol; From 0f8e82a2a2261fe35abd917a8be3af1472f756e7 Mon Sep 17 00:00:00 2001 From: Soares Chen Date: Sat, 23 May 2026 18:21:04 +0200 Subject: [PATCH 45/81] Implement ProviderStruct --- .../src/types/delegate_component/table.rs | 25 ++++++--- .../delegate_component/value/inner_table.rs | 47 +++++++++++++++-- crates/cgp-macro-core/src/types/mod.rs | 1 + .../src/types/provider_struct.rs | 51 +++++++++++++++++++ 4 files changed, 113 insertions(+), 11 deletions(-) create mode 100644 crates/cgp-macro-core/src/types/provider_struct.rs diff --git a/crates/cgp-macro-core/src/types/delegate_component/table.rs b/crates/cgp-macro-core/src/types/delegate_component/table.rs index 2183b48c..b8592f84 100644 --- a/crates/cgp-macro-core/src/types/delegate_component/table.rs +++ b/crates/cgp-macro-core/src/types/delegate_component/table.rs @@ -3,20 +3,30 @@ use syn::punctuated::Punctuated; use syn::token::Comma; use syn::{Ident, braced}; +use crate::traits::PeekKeyword; use crate::types::delegate_component::DelegateEntry; -use crate::types::generics::TypeGenerics; +use crate::types::generics::ImplGenerics; +use crate::types::keyword::Keyword; +use crate::types::keywords::New; pub struct DelegateTable { - pub table_ident: Ident, - pub table_generics: TypeGenerics, + pub impl_generics: ImplGenerics, + pub new: Option>, + pub table_type: Ident, pub entries: Punctuated, } impl Parse for DelegateTable { fn parse(input: ParseStream) -> syn::Result { - let table_ident = input.parse()?; + let impl_generics = input.parse()?; - let table_generics: TypeGenerics = input.parse()?; + let new = if input.peek_keyword::() { + Some(input.parse()?) + } else { + None + }; + + let table_type = input.parse()?; let entries = { let content; @@ -26,8 +36,9 @@ impl Parse for DelegateTable { }; Ok(Self { - table_ident, - table_generics, + impl_generics, + new, + table_type, entries, }) } diff --git a/crates/cgp-macro-core/src/types/delegate_component/value/inner_table.rs b/crates/cgp-macro-core/src/types/delegate_component/value/inner_table.rs index 4c579c73..dd7924e2 100644 --- a/crates/cgp-macro-core/src/types/delegate_component/value/inner_table.rs +++ b/crates/cgp-macro-core/src/types/delegate_component/value/inner_table.rs @@ -1,15 +1,18 @@ use syn::parse::{Parse, ParseStream}; -use syn::token::{Gt, Lt}; -use syn::{Ident, Type, parse_quote}; +use syn::punctuated::Punctuated; +use syn::token::{Comma, Gt, Lt}; +use syn::{Ident, Type, braced, parse_quote}; -use crate::types::delegate_component::{DelegateTable, EvalDelegateValue}; +use crate::types::delegate_component::{DelegateEntry, EvalDelegateValue}; +use crate::types::generics::TypeGenerics; use crate::types::keyword::Keyword; use crate::types::keywords::New; +use crate::types::provider_struct::ProviderStruct; pub struct DelegateValueWithInnerTable { pub new: Keyword, pub wrapper_ident: Ident, - pub inner_table: DelegateTable, + pub inner_table: InnerDelegateTable, } impl Parse for DelegateValueWithInnerTable { @@ -42,3 +45,39 @@ impl EvalDelegateValue for DelegateValueWithInnerTable { Ok(ty) } } + +pub struct InnerDelegateTable { + pub table_ident: Ident, + pub table_generics: TypeGenerics, + pub entries: Punctuated, +} + +impl Parse for InnerDelegateTable { + fn parse(input: ParseStream) -> syn::Result { + let table_ident = input.parse()?; + + let table_generics: TypeGenerics = input.parse()?; + + let entries = { + let content; + braced!(content in input); + + Punctuated::parse_terminated(&content)? + }; + + Ok(Self { + table_ident, + table_generics, + entries, + }) + } +} + +impl InnerDelegateTable { + pub fn to_provider_struct(&self) -> ProviderStruct { + let ident = self.table_ident.clone(); + let generics = self.table_generics.generics.clone(); + + ProviderStruct { ident, generics } + } +} diff --git a/crates/cgp-macro-core/src/types/mod.rs b/crates/cgp-macro-core/src/types/mod.rs index 0043dec2..362f929c 100644 --- a/crates/cgp-macro-core/src/types/mod.rs +++ b/crates/cgp-macro-core/src/types/mod.rs @@ -4,4 +4,5 @@ pub mod keyword; pub mod keywords; pub mod namespace; pub mod path; +pub mod provider_struct; pub mod symbol; diff --git a/crates/cgp-macro-core/src/types/provider_struct.rs b/crates/cgp-macro-core/src/types/provider_struct.rs new file mode 100644 index 00000000..21a07bb0 --- /dev/null +++ b/crates/cgp-macro-core/src/types/provider_struct.rs @@ -0,0 +1,51 @@ +use quote::quote; +use syn::punctuated::Punctuated; +use syn::token::Comma; +use syn::{GenericParam, Generics, Ident, ItemStruct, Type, parse2}; + +pub struct ProviderStruct { + pub ident: Ident, + pub generics: Generics, +} + +impl ProviderStruct { + pub fn to_item_struct(&self) -> syn::Result { + let struct_ident = &self.ident; + let struct_generics = &self.generics; + + if struct_generics.params.is_empty() { + parse2(quote! { + pub struct #struct_ident; + }) + } else { + let mut generic_params = struct_generics.params.clone(); + let mut phantom_params: Punctuated = Default::default(); + + for param in generic_params.iter_mut() { + match param { + GenericParam::Type(type_param) => { + type_param.colon_token = None; + type_param.bounds.clear(); + + let type_ident = &type_param.ident; + phantom_params.push(parse2(quote!( #type_ident ))?); + } + GenericParam::Lifetime(life_param) => { + life_param.colon_token = None; + life_param.bounds.clear(); + + let lifetime = &life_param.lifetime; + phantom_params.push(parse2(quote!( Life<#lifetime> ))?); + } + _ => {} + } + } + + parse2(quote! { + pub struct #struct_ident < #generic_params > ( + pub ::core::marker::PhantomData<( #phantom_params )> + ); + }) + } + } +} From fb343ded89565dcecc2e9475247065ba2645620a Mon Sep 17 00:00:00 2001 From: Soares Chen Date: Sat, 23 May 2026 18:24:27 +0200 Subject: [PATCH 46/81] Remove define_struct --- .../src/delegate_components/define_struct.rs | 41 ------------------- .../src/delegate_components/impl_delegate.rs | 8 +++- .../src/delegate_components/mod.rs | 2 - .../src/entrypoints/cgp_preset.rs | 9 +++- .../src/entrypoints/delegate_components.rs | 9 +++- 5 files changed, 20 insertions(+), 49 deletions(-) delete mode 100644 crates/cgp-macro-lib/src/delegate_components/define_struct.rs diff --git a/crates/cgp-macro-lib/src/delegate_components/define_struct.rs b/crates/cgp-macro-lib/src/delegate_components/define_struct.rs deleted file mode 100644 index 2a4bc308..00000000 --- a/crates/cgp-macro-lib/src/delegate_components/define_struct.rs +++ /dev/null @@ -1,41 +0,0 @@ -use quote::quote; -use syn::punctuated::Punctuated; -use syn::token::Comma; -use syn::{GenericParam, Generics, Ident, ItemStruct, Type, parse2}; - -pub fn define_struct(ident: &Ident, generics: &Generics) -> syn::Result { - if generics.params.is_empty() { - parse2(quote! { - pub struct #ident; - }) - } else { - let mut generic_params = generics.params.clone(); - let mut phantom_params: Punctuated = Default::default(); - - for param in generic_params.iter_mut() { - match param { - GenericParam::Type(type_param) => { - type_param.colon_token = None; - type_param.bounds.clear(); - - let type_ident = &type_param.ident; - phantom_params.push(parse2(quote!( #type_ident ))?); - } - GenericParam::Lifetime(life_param) => { - life_param.colon_token = None; - life_param.bounds.clear(); - - let lifetime = &life_param.lifetime; - phantom_params.push(parse2(quote!( Life<#lifetime> ))?); - } - _ => {} - } - } - - parse2(quote! { - pub struct #ident < #generic_params > ( - pub ::core::marker::PhantomData<( #phantom_params )> - ); - }) - } -} diff --git a/crates/cgp-macro-lib/src/delegate_components/impl_delegate.rs b/crates/cgp-macro-lib/src/delegate_components/impl_delegate.rs index c35a8ca0..d235f42c 100644 --- a/crates/cgp-macro-lib/src/delegate_components/impl_delegate.rs +++ b/crates/cgp-macro-lib/src/delegate_components/impl_delegate.rs @@ -4,13 +4,13 @@ use alloc::vec::Vec; use cgp_macro_core::functions::merge_generics; use cgp_macro_core::types::generics::ImplGenerics; +use cgp_macro_core::types::provider_struct::ProviderStruct; use proc_macro2::TokenStream; use quote::{ToTokens, quote}; use syn::punctuated::Punctuated; use syn::token::Comma; use syn::{ImplItem, ImplItemType, ItemImpl, Path, Type, parse2}; -use crate::delegate_components::define_struct; use crate::parse::{DelegateEntry, DelegateKey, DelegateMode, DelegateValue}; pub fn impl_delegate_components( @@ -40,7 +40,11 @@ where if let DelegateValue::New(value) = source { let struct_ident = &value.struct_ident; - let item_struct = define_struct(struct_ident, &value.struct_generics)?; + let item_struct = ProviderStruct { + ident: struct_ident.clone(), + generics: value.struct_generics.clone(), + } + .to_item_struct()?; let (impl_generics, type_generics, _) = value.struct_generics.split_for_impl(); diff --git a/crates/cgp-macro-lib/src/delegate_components/mod.rs b/crates/cgp-macro-lib/src/delegate_components/mod.rs index ab2ea3e7..c9f86cb6 100644 --- a/crates/cgp-macro-lib/src/delegate_components/mod.rs +++ b/crates/cgp-macro-lib/src/delegate_components/mod.rs @@ -1,5 +1,3 @@ -mod define_struct; mod impl_delegate; -pub use define_struct::*; pub use impl_delegate::*; diff --git a/crates/cgp-macro-lib/src/entrypoints/cgp_preset.rs b/crates/cgp-macro-lib/src/entrypoints/cgp_preset.rs index 4d2977ec..11d1bed7 100644 --- a/crates/cgp-macro-lib/src/entrypoints/cgp_preset.rs +++ b/crates/cgp-macro-lib/src/entrypoints/cgp_preset.rs @@ -1,13 +1,14 @@ use std::collections::HashSet; use cgp_macro_core::types::generics::ImplGenerics; +use cgp_macro_core::types::provider_struct::ProviderStruct; use proc_macro2::{Span, TokenStream}; use quote::{ToTokens, TokenStreamExt, quote}; use syn::punctuated::Punctuated; use syn::token::{At, Comma}; use syn::{GenericParam, Ident, ItemTrait, TypeParamBound, parse_quote, parse2}; -use crate::delegate_components::{define_struct, impl_delegate_components}; +use crate::delegate_components::impl_delegate_components; use crate::parse::{DefinePreset, DelegateEntry, SimpleType}; use crate::preset::{define_substitution_macro, impl_components_is_preset}; use crate::replace_self::to_snake_case_str; @@ -133,7 +134,11 @@ pub fn define_preset(body: TokenStream) -> syn::Result { &delegate_entries, ); - let provider_struct = define_struct(&provider_struct_name, &preset_generics.generics)?; + let provider_struct = ProviderStruct { + ident: provider_struct_name.clone(), + generics: preset_generics.generics.clone(), + } + .to_item_struct()?; let export_provider = match ast.provider_wrapper { Some(wrapper) => { diff --git a/crates/cgp-macro-lib/src/entrypoints/delegate_components.rs b/crates/cgp-macro-lib/src/entrypoints/delegate_components.rs index 1a8dde64..f595d9ac 100644 --- a/crates/cgp-macro-lib/src/entrypoints/delegate_components.rs +++ b/crates/cgp-macro-lib/src/entrypoints/delegate_components.rs @@ -1,9 +1,10 @@ use cgp_macro_core::types::generics::TypeGenerics; +use cgp_macro_core::types::provider_struct::ProviderStruct; use proc_macro2::TokenStream; use quote::ToTokens; use syn::parse2; -use crate::delegate_components::{define_struct, impl_delegate_components}; +use crate::delegate_components::impl_delegate_components; use crate::parse::{DelegateComponents, SimpleType}; pub fn delegate_components(body: TokenStream) -> syn::Result { @@ -19,7 +20,11 @@ pub fn delegate_components(body: TokenStream) -> syn::Result { let type_generics = target_type.generics.unwrap_or_default().generics; - let component_struct = define_struct(&target_type.name, &type_generics)?; + let component_struct = ProviderStruct { + ident: target_type.name, + generics: type_generics, + } + .to_item_struct()?; output.extend(component_struct.to_token_stream()); } From 857d13f0f38a2da2a1f927ea966ea8e20b559e04 Mon Sep 17 00:00:00 2001 From: Soares Chen Date: Sat, 23 May 2026 20:56:03 +0200 Subject: [PATCH 47/81] Derive Debug and Clone --- .../delegate_component/entry/combined.rs | 1 + .../types/delegate_component/entry/direct.rs | 1 + .../delegate_component/entry/namespace.rs | 1 + .../types/delegate_component/entry/normal.rs | 1 + .../types/delegate_component/entry/open.rs | 1 + .../types/delegate_component/key/combined.rs | 1 + .../src/types/delegate_component/key/multi.rs | 1 + .../src/types/delegate_component/key/path.rs | 1 + .../types/delegate_component/key/single.rs | 1 + .../types/delegate_component/table/inner.rs | 49 +++++++++++++++++++ .../{table.rs => table/main.rs} | 0 .../src/types/delegate_component/table/mod.rs | 5 ++ .../delegate_component/value/combined.rs | 1 + .../delegate_component/value/inner_table.rs | 48 ++++-------------- .../src/types/generics/type_generics.rs | 2 +- crates/cgp-macro-core/src/types/keyword.rs | 16 ++++++ 16 files changed, 90 insertions(+), 40 deletions(-) create mode 100644 crates/cgp-macro-core/src/types/delegate_component/table/inner.rs rename crates/cgp-macro-core/src/types/delegate_component/{table.rs => table/main.rs} (100%) create mode 100644 crates/cgp-macro-core/src/types/delegate_component/table/mod.rs diff --git a/crates/cgp-macro-core/src/types/delegate_component/entry/combined.rs b/crates/cgp-macro-core/src/types/delegate_component/entry/combined.rs index 64db7664..2ac6fe4c 100644 --- a/crates/cgp-macro-core/src/types/delegate_component/entry/combined.rs +++ b/crates/cgp-macro-core/src/types/delegate_component/entry/combined.rs @@ -8,6 +8,7 @@ use crate::types::delegate_component::{ }; use crate::types::keywords::{Namespace, Open}; +#[derive(Debug, Clone)] pub enum DelegateEntry { Normal(NormalDelegateEntry), Direct(DirectDelegateEntry), diff --git a/crates/cgp-macro-core/src/types/delegate_component/entry/direct.rs b/crates/cgp-macro-core/src/types/delegate_component/entry/direct.rs index 3b5a365f..440d0eb1 100644 --- a/crates/cgp-macro-core/src/types/delegate_component/entry/direct.rs +++ b/crates/cgp-macro-core/src/types/delegate_component/entry/direct.rs @@ -7,6 +7,7 @@ use crate::types::delegate_component::{ EvaluatedDelegateEntry, }; +#[derive(Debug, Clone)] pub struct DirectDelegateEntry { pub key: DelegateKey, pub arrow: RArrow, diff --git a/crates/cgp-macro-core/src/types/delegate_component/entry/namespace.rs b/crates/cgp-macro-core/src/types/delegate_component/entry/namespace.rs index 1d1b83dc..0138676e 100644 --- a/crates/cgp-macro-core/src/types/delegate_component/entry/namespace.rs +++ b/crates/cgp-macro-core/src/types/delegate_component/entry/namespace.rs @@ -6,6 +6,7 @@ use crate::types::delegate_component::{EvalDelegateEntry, EvaluatedDelegateEntry use crate::types::keyword::Keyword; use crate::types::keywords::Namespace; +#[derive(Debug, Clone)] pub struct NamespaceDelegateEntry { pub namespace: Keyword, pub ident: Ident, diff --git a/crates/cgp-macro-core/src/types/delegate_component/entry/normal.rs b/crates/cgp-macro-core/src/types/delegate_component/entry/normal.rs index 18d09af4..4f41aabe 100644 --- a/crates/cgp-macro-core/src/types/delegate_component/entry/normal.rs +++ b/crates/cgp-macro-core/src/types/delegate_component/entry/normal.rs @@ -6,6 +6,7 @@ use crate::types::delegate_component::{ EvaluatedDelegateEntry, }; +#[derive(Debug, Clone)] pub struct NormalDelegateEntry { pub key: DelegateKey, pub colon: Colon, diff --git a/crates/cgp-macro-core/src/types/delegate_component/entry/open.rs b/crates/cgp-macro-core/src/types/delegate_component/entry/open.rs index afcf1b38..e46dbce8 100644 --- a/crates/cgp-macro-core/src/types/delegate_component/entry/open.rs +++ b/crates/cgp-macro-core/src/types/delegate_component/entry/open.rs @@ -8,6 +8,7 @@ use crate::types::delegate_component::{EvalDelegateEntry, EvaluatedDelegateEntry use crate::types::keyword::Keyword; use crate::types::keywords::Open; +#[derive(Debug, Clone)] pub struct OpenDelegateEntry { pub open: Keyword, pub components: Punctuated, diff --git a/crates/cgp-macro-core/src/types/delegate_component/key/combined.rs b/crates/cgp-macro-core/src/types/delegate_component/key/combined.rs index 33169641..04df43d4 100644 --- a/crates/cgp-macro-core/src/types/delegate_component/key/combined.rs +++ b/crates/cgp-macro-core/src/types/delegate_component/key/combined.rs @@ -6,6 +6,7 @@ use crate::types::delegate_component::{ }; use crate::types::generics::ImplGenerics; +#[derive(Debug, Clone)] pub enum DelegateKey { Single(SingleDelegateKey), Multi(MultiDelegateKey), diff --git a/crates/cgp-macro-core/src/types/delegate_component/key/multi.rs b/crates/cgp-macro-core/src/types/delegate_component/key/multi.rs index a904f9d9..c571ae0b 100644 --- a/crates/cgp-macro-core/src/types/delegate_component/key/multi.rs +++ b/crates/cgp-macro-core/src/types/delegate_component/key/multi.rs @@ -5,6 +5,7 @@ use syn::token::Comma; use crate::types::delegate_component::{EvalDelegateKey, EvaluatedDelegateKey, SingleDelegateKey}; +#[derive(Debug, Clone)] pub struct MultiDelegateKey { pub keys: Punctuated, } diff --git a/crates/cgp-macro-core/src/types/delegate_component/key/path.rs b/crates/cgp-macro-core/src/types/delegate_component/key/path.rs index fb4f5868..32e645c0 100644 --- a/crates/cgp-macro-core/src/types/delegate_component/key/path.rs +++ b/crates/cgp-macro-core/src/types/delegate_component/key/path.rs @@ -7,6 +7,7 @@ use crate::types::delegate_component::{EvalDelegateKey, EvaluatedDelegateKey}; use crate::types::generics::ImplGenerics; use crate::types::path::PathHead; +#[derive(Debug, Clone)] pub struct PathDelegateKey { pub generics: ImplGenerics, pub at: At, diff --git a/crates/cgp-macro-core/src/types/delegate_component/key/single.rs b/crates/cgp-macro-core/src/types/delegate_component/key/single.rs index 0cddac02..6e234165 100644 --- a/crates/cgp-macro-core/src/types/delegate_component/key/single.rs +++ b/crates/cgp-macro-core/src/types/delegate_component/key/single.rs @@ -4,6 +4,7 @@ use syn::parse::{Parse, ParseStream}; use crate::types::delegate_component::{EvalDelegateKey, EvaluatedDelegateKey}; use crate::types::generics::ImplGenerics; +#[derive(Debug, Clone)] pub struct SingleDelegateKey { pub generics: ImplGenerics, pub ty: Type, diff --git a/crates/cgp-macro-core/src/types/delegate_component/table/inner.rs b/crates/cgp-macro-core/src/types/delegate_component/table/inner.rs new file mode 100644 index 00000000..e6459300 --- /dev/null +++ b/crates/cgp-macro-core/src/types/delegate_component/table/inner.rs @@ -0,0 +1,49 @@ +use syn::parse::{Parse, ParseStream}; +use syn::punctuated::Punctuated; +use syn::token::Comma; +use syn::{Ident, braced}; + +use crate::types::delegate_component::DelegateEntry; +use crate::types::generics::TypeGenerics; +use crate::types::provider_struct::ProviderStruct; + +pub trait ExtractInnerDelegateTables { + fn inner_tables(&self) -> Vec; +} + +#[derive(Debug, Clone)] +pub struct InnerDelegateTable { + pub table_ident: Ident, + pub table_generics: TypeGenerics, + pub entries: Punctuated, +} + +impl Parse for InnerDelegateTable { + fn parse(input: ParseStream) -> syn::Result { + let table_ident = input.parse()?; + + let table_generics: TypeGenerics = input.parse()?; + + let entries = { + let content; + braced!(content in input); + + Punctuated::parse_terminated(&content)? + }; + + Ok(Self { + table_ident, + table_generics, + entries, + }) + } +} + +impl InnerDelegateTable { + pub fn to_provider_struct(&self) -> ProviderStruct { + let ident = self.table_ident.clone(); + let generics = self.table_generics.generics.clone(); + + ProviderStruct { ident, generics } + } +} diff --git a/crates/cgp-macro-core/src/types/delegate_component/table.rs b/crates/cgp-macro-core/src/types/delegate_component/table/main.rs similarity index 100% rename from crates/cgp-macro-core/src/types/delegate_component/table.rs rename to crates/cgp-macro-core/src/types/delegate_component/table/main.rs diff --git a/crates/cgp-macro-core/src/types/delegate_component/table/mod.rs b/crates/cgp-macro-core/src/types/delegate_component/table/mod.rs new file mode 100644 index 00000000..0e43a88d --- /dev/null +++ b/crates/cgp-macro-core/src/types/delegate_component/table/mod.rs @@ -0,0 +1,5 @@ +mod inner; +mod main; + +pub use inner::*; +pub use main::*; diff --git a/crates/cgp-macro-core/src/types/delegate_component/value/combined.rs b/crates/cgp-macro-core/src/types/delegate_component/value/combined.rs index 274fa3a4..dfe25a9e 100644 --- a/crates/cgp-macro-core/src/types/delegate_component/value/combined.rs +++ b/crates/cgp-macro-core/src/types/delegate_component/value/combined.rs @@ -4,6 +4,7 @@ use syn::parse::{Parse, ParseStream}; use crate::types::delegate_component::{DelegateValueWithInnerTable, EvalDelegateValue}; +#[derive(Debug, Clone)] pub enum DelegateValue { Type(Type), WithTable(DelegateValueWithInnerTable), diff --git a/crates/cgp-macro-core/src/types/delegate_component/value/inner_table.rs b/crates/cgp-macro-core/src/types/delegate_component/value/inner_table.rs index dd7924e2..dd9168da 100644 --- a/crates/cgp-macro-core/src/types/delegate_component/value/inner_table.rs +++ b/crates/cgp-macro-core/src/types/delegate_component/value/inner_table.rs @@ -1,14 +1,14 @@ use syn::parse::{Parse, ParseStream}; -use syn::punctuated::Punctuated; -use syn::token::{Comma, Gt, Lt}; -use syn::{Ident, Type, braced, parse_quote}; +use syn::token::{Gt, Lt}; +use syn::{Ident, Type, parse_quote}; -use crate::types::delegate_component::{DelegateEntry, EvalDelegateValue}; -use crate::types::generics::TypeGenerics; +use crate::types::delegate_component::{ + EvalDelegateValue, ExtractInnerDelegateTables, InnerDelegateTable, +}; use crate::types::keyword::Keyword; use crate::types::keywords::New; -use crate::types::provider_struct::ProviderStruct; +#[derive(Debug, Clone)] pub struct DelegateValueWithInnerTable { pub new: Keyword, pub wrapper_ident: Ident, @@ -46,38 +46,8 @@ impl EvalDelegateValue for DelegateValueWithInnerTable { } } -pub struct InnerDelegateTable { - pub table_ident: Ident, - pub table_generics: TypeGenerics, - pub entries: Punctuated, -} - -impl Parse for InnerDelegateTable { - fn parse(input: ParseStream) -> syn::Result { - let table_ident = input.parse()?; - - let table_generics: TypeGenerics = input.parse()?; - - let entries = { - let content; - braced!(content in input); - - Punctuated::parse_terminated(&content)? - }; - - Ok(Self { - table_ident, - table_generics, - entries, - }) - } -} - -impl InnerDelegateTable { - pub fn to_provider_struct(&self) -> ProviderStruct { - let ident = self.table_ident.clone(); - let generics = self.table_generics.generics.clone(); - - ProviderStruct { ident, generics } +impl ExtractInnerDelegateTables for DelegateValueWithInnerTable { + fn inner_tables(&self) -> Vec { + vec![self.inner_table.clone()] } } diff --git a/crates/cgp-macro-core/src/types/generics/type_generics.rs b/crates/cgp-macro-core/src/types/generics/type_generics.rs index e2a897dc..22289b01 100644 --- a/crates/cgp-macro-core/src/types/generics/type_generics.rs +++ b/crates/cgp-macro-core/src/types/generics/type_generics.rs @@ -5,7 +5,7 @@ use quote::ToTokens; use syn::parse::{Parse, ParseStream}; use syn::{Error, Generics, parse2}; -#[derive(Clone, Default)] +#[derive(Debug, Clone, Default)] pub struct TypeGenerics { pub generics: Generics, } diff --git a/crates/cgp-macro-core/src/types/keyword.rs b/crates/cgp-macro-core/src/types/keyword.rs index ded752ae..d676014e 100644 --- a/crates/cgp-macro-core/src/types/keyword.rs +++ b/crates/cgp-macro-core/src/types/keyword.rs @@ -1,3 +1,4 @@ +use core::fmt::Debug; use core::marker::PhantomData; use proc_macro2::Span; @@ -11,6 +12,21 @@ pub struct Keyword { pub phantom: PhantomData, } +impl Debug for Keyword { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("keyword").field("ident", &K::IDENT).finish() + } +} + +impl Clone for Keyword { + fn clone(&self) -> Self { + Self { + span: self.span.clone(), + phantom: PhantomData, + } + } +} + impl Parse for Keyword where K: IsKeyword, From cf11ccccafecf61d81ca0319e3c2577d869a3b62 Mon Sep 17 00:00:00 2001 From: Soares Chen Date: Sat, 23 May 2026 21:03:44 +0200 Subject: [PATCH 48/81] Implement ExtractInnerDelegateTables --- .../src/types/delegate_component/entry/combined.rs | 14 +++++++++++++- .../src/types/delegate_component/entry/direct.rs | 8 +++++++- .../src/types/delegate_component/entry/normal.rs | 8 +++++++- .../src/types/delegate_component/table/inner.rs | 11 ++++++++++- .../src/types/delegate_component/value/combined.rs | 13 ++++++++++++- .../types/delegate_component/value/inner_table.rs | 7 +++++-- 6 files changed, 54 insertions(+), 7 deletions(-) diff --git a/crates/cgp-macro-core/src/types/delegate_component/entry/combined.rs b/crates/cgp-macro-core/src/types/delegate_component/entry/combined.rs index 2ac6fe4c..7d6f1a40 100644 --- a/crates/cgp-macro-core/src/types/delegate_component/entry/combined.rs +++ b/crates/cgp-macro-core/src/types/delegate_component/entry/combined.rs @@ -4,7 +4,8 @@ use syn::parse::{Parse, ParseStream}; use crate::traits::PeekKeyword; use crate::types::delegate_component::{ DelegateMode, DirectDelegateEntry, EvalDelegateEntry, EvaluatedDelegateEntry, - NamespaceDelegateEntry, NormalDelegateEntry, OpenDelegateEntry, + ExtractInnerDelegateTables, InnerDelegateTable, NamespaceDelegateEntry, NormalDelegateEntry, + OpenDelegateEntry, }; use crate::types::keywords::{Namespace, Open}; @@ -53,3 +54,14 @@ impl EvalDelegateEntry for DelegateEntry { } } } + +impl ExtractInnerDelegateTables for DelegateEntry { + fn extract_inner_tables(&self) -> Vec { + match self { + Self::Normal(entry) => entry.extract_inner_tables(), + Self::Direct(entry) => entry.extract_inner_tables(), + Self::Namespace(_) => Vec::new(), + Self::Open(_) => Vec::new(), + } + } +} diff --git a/crates/cgp-macro-core/src/types/delegate_component/entry/direct.rs b/crates/cgp-macro-core/src/types/delegate_component/entry/direct.rs index 440d0eb1..b2aa7c6c 100644 --- a/crates/cgp-macro-core/src/types/delegate_component/entry/direct.rs +++ b/crates/cgp-macro-core/src/types/delegate_component/entry/direct.rs @@ -4,7 +4,7 @@ use syn::{Type, parse_quote}; use crate::exports::DelegateComponent; use crate::types::delegate_component::{ DelegateKey, DelegateValue, EvalDelegateEntry, EvalDelegateKey, EvalDelegateValue, - EvaluatedDelegateEntry, + EvaluatedDelegateEntry, ExtractInnerDelegateTables, InnerDelegateTable, }; #[derive(Debug, Clone)] @@ -50,3 +50,9 @@ impl EvalDelegateEntry for DirectDelegateEntry { Ok(entries) } } + +impl ExtractInnerDelegateTables for DirectDelegateEntry { + fn extract_inner_tables(&self) -> Vec { + self.value.extract_inner_tables() + } +} diff --git a/crates/cgp-macro-core/src/types/delegate_component/entry/normal.rs b/crates/cgp-macro-core/src/types/delegate_component/entry/normal.rs index 4f41aabe..7636f5b4 100644 --- a/crates/cgp-macro-core/src/types/delegate_component/entry/normal.rs +++ b/crates/cgp-macro-core/src/types/delegate_component/entry/normal.rs @@ -3,7 +3,7 @@ use syn::token::Colon; use crate::types::delegate_component::{ DelegateKey, DelegateValue, EvalDelegateEntry, EvalDelegateKey, EvalDelegateValue, - EvaluatedDelegateEntry, + EvaluatedDelegateEntry, ExtractInnerDelegateTables, InnerDelegateTable, }; #[derive(Debug, Clone)] @@ -31,3 +31,9 @@ impl EvalDelegateEntry for NormalDelegateEntry { Ok(entries) } } + +impl ExtractInnerDelegateTables for NormalDelegateEntry { + fn extract_inner_tables(&self) -> Vec { + self.value.extract_inner_tables() + } +} diff --git a/crates/cgp-macro-core/src/types/delegate_component/table/inner.rs b/crates/cgp-macro-core/src/types/delegate_component/table/inner.rs index e6459300..5475ae8d 100644 --- a/crates/cgp-macro-core/src/types/delegate_component/table/inner.rs +++ b/crates/cgp-macro-core/src/types/delegate_component/table/inner.rs @@ -8,7 +8,7 @@ use crate::types::generics::TypeGenerics; use crate::types::provider_struct::ProviderStruct; pub trait ExtractInnerDelegateTables { - fn inner_tables(&self) -> Vec; + fn extract_inner_tables(&self) -> Vec; } #[derive(Debug, Clone)] @@ -47,3 +47,12 @@ impl InnerDelegateTable { ProviderStruct { ident, generics } } } + +impl ExtractInnerDelegateTables for InnerDelegateTable { + fn extract_inner_tables(&self) -> Vec { + self.entries + .iter() + .flat_map(|entry| entry.extract_inner_tables()) + .collect() + } +} diff --git a/crates/cgp-macro-core/src/types/delegate_component/value/combined.rs b/crates/cgp-macro-core/src/types/delegate_component/value/combined.rs index dfe25a9e..bce6fb69 100644 --- a/crates/cgp-macro-core/src/types/delegate_component/value/combined.rs +++ b/crates/cgp-macro-core/src/types/delegate_component/value/combined.rs @@ -2,7 +2,9 @@ use syn::Type; use syn::parse::discouraged::Speculative; use syn::parse::{Parse, ParseStream}; -use crate::types::delegate_component::{DelegateValueWithInnerTable, EvalDelegateValue}; +use crate::types::delegate_component::{ + DelegateValueWithInnerTable, EvalDelegateValue, ExtractInnerDelegateTables, InnerDelegateTable, +}; #[derive(Debug, Clone)] pub enum DelegateValue { @@ -32,3 +34,12 @@ impl EvalDelegateValue for DelegateValue { } } } + +impl ExtractInnerDelegateTables for DelegateValue { + fn extract_inner_tables(&self) -> Vec { + match self { + Self::Type(_) => Vec::new(), + Self::WithTable(value) => value.extract_inner_tables(), + } + } +} diff --git a/crates/cgp-macro-core/src/types/delegate_component/value/inner_table.rs b/crates/cgp-macro-core/src/types/delegate_component/value/inner_table.rs index dd9168da..d09e42c0 100644 --- a/crates/cgp-macro-core/src/types/delegate_component/value/inner_table.rs +++ b/crates/cgp-macro-core/src/types/delegate_component/value/inner_table.rs @@ -47,7 +47,10 @@ impl EvalDelegateValue for DelegateValueWithInnerTable { } impl ExtractInnerDelegateTables for DelegateValueWithInnerTable { - fn inner_tables(&self) -> Vec { - vec![self.inner_table.clone()] + fn extract_inner_tables(&self) -> Vec { + let mut inner_tables = self.inner_table.extract_inner_tables(); + inner_tables.push(self.inner_table.clone()); + + inner_tables } } From dab0faa918e561bb8203ef9c42a33c750c0972e8 Mon Sep 17 00:00:00 2001 From: Soares Chen Date: Sat, 23 May 2026 21:51:27 +0200 Subject: [PATCH 49/81] Implement build_impls --- Cargo.lock | 1 + crates/cgp-macro-core/Cargo.toml | 1 + .../src/types/delegate_component/entries.rs | 54 +++++++++++++++++++ .../types/delegate_component/entry/eval.rs | 16 ++++-- .../src/types/delegate_component/mod.rs | 2 + .../types/delegate_component/table/inner.rs | 34 +++++++----- 6 files changed, 91 insertions(+), 17 deletions(-) create mode 100644 crates/cgp-macro-core/src/types/delegate_component/entries.rs diff --git a/Cargo.lock b/Cargo.lock index 42982093..1543564a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -172,6 +172,7 @@ dependencies = [ name = "cgp-macro-core" version = "0.7.0" dependencies = [ + "itertools", "proc-macro2", "quote", "syn", diff --git a/crates/cgp-macro-core/Cargo.toml b/crates/cgp-macro-core/Cargo.toml index ef93dd8a..2d69a19d 100644 --- a/crates/cgp-macro-core/Cargo.toml +++ b/crates/cgp-macro-core/Cargo.toml @@ -18,3 +18,4 @@ default = [] syn = { version = "2.0.95", features = [ "full", "extra-traits", "visit", "visit-mut" ] } quote = "1.0.38" proc-macro2 = "1.0.92" +itertools = "0.14.0" diff --git a/crates/cgp-macro-core/src/types/delegate_component/entries.rs b/crates/cgp-macro-core/src/types/delegate_component/entries.rs new file mode 100644 index 00000000..82bb31a0 --- /dev/null +++ b/crates/cgp-macro-core/src/types/delegate_component/entries.rs @@ -0,0 +1,54 @@ +use syn::parse::{Parse, ParseStream}; +use syn::punctuated::Punctuated; +use syn::token::Comma; +use syn::{Generics, ItemImpl, Type}; + +use crate::types::delegate_component::{ + DelegateEntry, EvalDelegateEntry, ExtractInnerDelegateTables, InnerDelegateTable, +}; + +#[derive(Debug, Clone)] +pub struct DelegateEntries { + pub entries: Punctuated, +} + +impl Parse for DelegateEntries { + fn parse(input: ParseStream) -> syn::Result { + let entries = Punctuated::parse_terminated(input)?; + Ok(Self { entries }) + } +} + +impl DelegateEntries { + pub fn build_impls( + &self, + table_type: &Type, + outer_generics: &Generics, + ) -> syn::Result> { + let mut item_impls = Vec::new(); + + for entry in &self.entries { + let evaluated_entries = entry.eval(&table_type)?; + for evaluated_entry in evaluated_entries { + let delegate_component_impl = + evaluated_entry.build_delegate_component_impl(outer_generics)?; + let is_provider_impl = + evaluated_entry.build_is_provider_for_impl(outer_generics)?; + + item_impls.push(delegate_component_impl); + item_impls.push(is_provider_impl); + } + } + + Ok(item_impls) + } +} + +impl ExtractInnerDelegateTables for DelegateEntries { + fn extract_inner_tables(&self) -> Vec { + self.entries + .iter() + .flat_map(|entry| entry.extract_inner_tables()) + .collect() + } +} diff --git a/crates/cgp-macro-core/src/types/delegate_component/entry/eval.rs b/crates/cgp-macro-core/src/types/delegate_component/entry/eval.rs index 869a0cd0..9407b822 100644 --- a/crates/cgp-macro-core/src/types/delegate_component/entry/eval.rs +++ b/crates/cgp-macro-core/src/types/delegate_component/entry/eval.rs @@ -2,6 +2,7 @@ use quote::quote; use syn::{Generics, ItemImpl, Type, parse_quote, parse2}; use crate::exports::{DelegateComponent, IsProviderFor}; +use crate::functions::merge_generics; pub struct EvaluatedDelegateEntry { pub table_type: Type, @@ -15,9 +16,14 @@ pub trait EvalDelegateEntry { } impl EvaluatedDelegateEntry { - pub fn to_delegate_component_impl(&self) -> syn::Result { + pub fn build_delegate_component_impl( + &self, + outer_generics: &Generics, + ) -> syn::Result { let table_type = &self.table_type; - let generics = &self.generics; + + let generics = merge_generics(outer_generics, &self.generics); + let key = &self.key; let value = &self.value; @@ -34,9 +40,11 @@ impl EvaluatedDelegateEntry { }) } - pub fn to_is_provider_for_impl(&self) -> syn::Result { + pub fn build_is_provider_for_impl(&self, outer_generics: &Generics) -> syn::Result { let table_type = &self.table_type; - let mut generics = self.generics.clone(); + + let mut generics = merge_generics(outer_generics, &self.generics); + let key = &self.key; let value = &self.value; diff --git a/crates/cgp-macro-core/src/types/delegate_component/mod.rs b/crates/cgp-macro-core/src/types/delegate_component/mod.rs index ccf2c51e..315e0b66 100644 --- a/crates/cgp-macro-core/src/types/delegate_component/mod.rs +++ b/crates/cgp-macro-core/src/types/delegate_component/mod.rs @@ -1,8 +1,10 @@ +mod entries; mod entry; mod key; mod table; mod value; +pub use entries::*; pub use entry::*; pub use key::*; pub use table::*; diff --git a/crates/cgp-macro-core/src/types/delegate_component/table/inner.rs b/crates/cgp-macro-core/src/types/delegate_component/table/inner.rs index 5475ae8d..5472d19e 100644 --- a/crates/cgp-macro-core/src/types/delegate_component/table/inner.rs +++ b/crates/cgp-macro-core/src/types/delegate_component/table/inner.rs @@ -1,9 +1,8 @@ +use quote::quote; use syn::parse::{Parse, ParseStream}; -use syn::punctuated::Punctuated; -use syn::token::Comma; -use syn::{Ident, braced}; +use syn::{Ident, ItemImpl, Type, braced, parse2}; -use crate::types::delegate_component::DelegateEntry; +use crate::types::delegate_component::DelegateEntries; use crate::types::generics::TypeGenerics; use crate::types::provider_struct::ProviderStruct; @@ -15,7 +14,7 @@ pub trait ExtractInnerDelegateTables { pub struct InnerDelegateTable { pub table_ident: Ident, pub table_generics: TypeGenerics, - pub entries: Punctuated, + pub entries: DelegateEntries, } impl Parse for InnerDelegateTable { @@ -25,10 +24,10 @@ impl Parse for InnerDelegateTable { let table_generics: TypeGenerics = input.parse()?; let entries = { - let content; - braced!(content in input); + let body; + braced!(body in input); - Punctuated::parse_terminated(&content)? + body.parse()? }; Ok(Self { @@ -40,19 +39,28 @@ impl Parse for InnerDelegateTable { } impl InnerDelegateTable { - pub fn to_provider_struct(&self) -> ProviderStruct { + pub fn build_table_type(&self) -> syn::Result { + let ident = &self.table_ident; + let type_generics = self.table_generics.split_for_impl().1; + + parse2(quote!( #ident #type_generics )) + } + + pub fn build_provider_struct(&self) -> ProviderStruct { let ident = self.table_ident.clone(); let generics = self.table_generics.generics.clone(); ProviderStruct { ident, generics } } + + pub fn build_impls(&self) -> syn::Result> { + let table_type = self.build_table_type()?; + self.entries.build_impls(&table_type, &self.table_generics) + } } impl ExtractInnerDelegateTables for InnerDelegateTable { fn extract_inner_tables(&self) -> Vec { - self.entries - .iter() - .flat_map(|entry| entry.extract_inner_tables()) - .collect() + self.entries.extract_inner_tables() } } From 570f108967fb99d150ff151ca460631b7785b56c Mon Sep 17 00:00:00 2001 From: Soares Chen Date: Sat, 23 May 2026 21:53:43 +0200 Subject: [PATCH 50/81] Update namespace and open syntax --- .../delegate_component/entry/namespace.rs | 9 +-------- .../types/delegate_component/entry/open.rs | 19 +++++++++---------- 2 files changed, 10 insertions(+), 18 deletions(-) diff --git a/crates/cgp-macro-core/src/types/delegate_component/entry/namespace.rs b/crates/cgp-macro-core/src/types/delegate_component/entry/namespace.rs index 0138676e..568d67dc 100644 --- a/crates/cgp-macro-core/src/types/delegate_component/entry/namespace.rs +++ b/crates/cgp-macro-core/src/types/delegate_component/entry/namespace.rs @@ -1,5 +1,4 @@ use syn::parse::{Parse, ParseStream}; -use syn::token::Semi; use syn::{Ident, Type, parse_quote}; use crate::types::delegate_component::{EvalDelegateEntry, EvaluatedDelegateEntry}; @@ -10,20 +9,14 @@ use crate::types::keywords::Namespace; pub struct NamespaceDelegateEntry { pub namespace: Keyword, pub ident: Ident, - pub semi: Semi, } impl Parse for NamespaceDelegateEntry { fn parse(input: ParseStream) -> syn::Result { let namespace = input.parse()?; let ident = input.parse()?; - let semi = input.parse()?; - Ok(Self { - namespace, - ident, - semi, - }) + Ok(Self { namespace, ident }) } } diff --git a/crates/cgp-macro-core/src/types/delegate_component/entry/open.rs b/crates/cgp-macro-core/src/types/delegate_component/entry/open.rs index e46dbce8..ebdbd1aa 100644 --- a/crates/cgp-macro-core/src/types/delegate_component/entry/open.rs +++ b/crates/cgp-macro-core/src/types/delegate_component/entry/open.rs @@ -1,7 +1,7 @@ use syn::parse::{Parse, ParseStream}; use syn::punctuated::Punctuated; -use syn::token::{Comma, Semi}; -use syn::{Type, parse_quote}; +use syn::token::Comma; +use syn::{Type, braced, parse_quote}; use crate::exports::{Nil, PathCons, RedirectLookup}; use crate::types::delegate_component::{EvalDelegateEntry, EvaluatedDelegateEntry}; @@ -12,21 +12,20 @@ use crate::types::keywords::Open; pub struct OpenDelegateEntry { pub open: Keyword, pub components: Punctuated, - pub semi: Semi, } impl Parse for OpenDelegateEntry { fn parse(input: ParseStream) -> syn::Result { let open = input.parse()?; - let components: Punctuated = Punctuated::parse_separated_nonempty(input)?; - let semi = input.parse()?; + let components: Punctuated = { + let body; + braced!(body in input); - Ok(Self { - open, - components, - semi, - }) + Punctuated::parse_terminated(&body)? + }; + + Ok(Self { open, components }) } } From 781d0e0084e6d32a83b8e16f24a1d779d4dae6f2 Mon Sep 17 00:00:00 2001 From: Soares Chen Date: Sat, 23 May 2026 22:13:52 +0200 Subject: [PATCH 51/81] Implement eval for DelegateTable --- .../src/types/delegate_component/entries.rs | 2 + .../types/delegate_component/table/inner.rs | 2 +- .../types/delegate_component/table/main.rs | 60 ++++++++++++++++--- crates/cgp-macro-core/src/types/ident_type.rs | 18 ++++++ crates/cgp-macro-core/src/types/mod.rs | 1 + 5 files changed, 73 insertions(+), 10 deletions(-) create mode 100644 crates/cgp-macro-core/src/types/ident_type.rs diff --git a/crates/cgp-macro-core/src/types/delegate_component/entries.rs b/crates/cgp-macro-core/src/types/delegate_component/entries.rs index 82bb31a0..47f8e904 100644 --- a/crates/cgp-macro-core/src/types/delegate_component/entries.rs +++ b/crates/cgp-macro-core/src/types/delegate_component/entries.rs @@ -29,9 +29,11 @@ impl DelegateEntries { for entry in &self.entries { let evaluated_entries = entry.eval(&table_type)?; + for evaluated_entry in evaluated_entries { let delegate_component_impl = evaluated_entry.build_delegate_component_impl(outer_generics)?; + let is_provider_impl = evaluated_entry.build_is_provider_for_impl(outer_generics)?; diff --git a/crates/cgp-macro-core/src/types/delegate_component/table/inner.rs b/crates/cgp-macro-core/src/types/delegate_component/table/inner.rs index 5472d19e..d9777820 100644 --- a/crates/cgp-macro-core/src/types/delegate_component/table/inner.rs +++ b/crates/cgp-macro-core/src/types/delegate_component/table/inner.rs @@ -46,7 +46,7 @@ impl InnerDelegateTable { parse2(quote!( #ident #type_generics )) } - pub fn build_provider_struct(&self) -> ProviderStruct { + pub fn build_table_struct(&self) -> ProviderStruct { let ident = self.table_ident.clone(); let generics = self.table_generics.generics.clone(); diff --git a/crates/cgp-macro-core/src/types/delegate_component/table/main.rs b/crates/cgp-macro-core/src/types/delegate_component/table/main.rs index b8592f84..a887e4e4 100644 --- a/crates/cgp-macro-core/src/types/delegate_component/table/main.rs +++ b/crates/cgp-macro-core/src/types/delegate_component/table/main.rs @@ -1,19 +1,25 @@ +use quote::ToTokens; use syn::parse::{Parse, ParseStream}; -use syn::punctuated::Punctuated; -use syn::token::Comma; -use syn::{Ident, braced}; +use syn::{ItemImpl, ItemStruct, Type, braced, parse2}; use crate::traits::PeekKeyword; -use crate::types::delegate_component::DelegateEntry; +use crate::types::delegate_component::{DelegateEntries, ExtractInnerDelegateTables}; use crate::types::generics::ImplGenerics; +use crate::types::ident_type::IdentType; use crate::types::keyword::Keyword; use crate::types::keywords::New; +use crate::types::provider_struct::ProviderStruct; pub struct DelegateTable { pub impl_generics: ImplGenerics, pub new: Option>, - pub table_type: Ident, - pub entries: Punctuated, + pub table_type: Type, + pub entries: DelegateEntries, +} + +pub struct EvaluatedDelegateTable { + pub item_impls: Vec, + pub item_structs: Vec, } impl Parse for DelegateTable { @@ -29,10 +35,10 @@ impl Parse for DelegateTable { let table_type = input.parse()?; let entries = { - let content; - braced!(content in input); + let body; + braced!(body in input); - Punctuated::parse_terminated(&content)? + body.parse()? }; Ok(Self { @@ -43,3 +49,39 @@ impl Parse for DelegateTable { }) } } + +impl DelegateTable { + pub fn eval(&self) -> syn::Result { + let mut item_impls = Vec::new(); + let mut item_structs = Vec::new(); + + if self.new.is_some() { + let struct_type: IdentType = parse2(self.table_type.to_token_stream())?; + item_structs.push( + ProviderStruct { + ident: struct_type.ident, + generics: struct_type.generics.generics, + } + .to_item_struct()?, + ); + } + + item_impls.extend( + self.entries + .build_impls(&self.table_type, &self.impl_generics)?, + ); + + let inner_tables = self.entries.extract_inner_tables(); + + for inner_table in inner_tables { + item_structs.push(inner_table.build_table_struct().to_item_struct()?); + + item_impls.extend(inner_table.build_impls()?); + } + + Ok(EvaluatedDelegateTable { + item_impls, + item_structs, + }) + } +} diff --git a/crates/cgp-macro-core/src/types/ident_type.rs b/crates/cgp-macro-core/src/types/ident_type.rs new file mode 100644 index 00000000..417836c8 --- /dev/null +++ b/crates/cgp-macro-core/src/types/ident_type.rs @@ -0,0 +1,18 @@ +use syn::Ident; +use syn::parse::{Parse, ParseStream}; + +use crate::types::generics::TypeGenerics; + +pub struct IdentType { + pub ident: Ident, + pub generics: TypeGenerics, +} + +impl Parse for IdentType { + fn parse(input: ParseStream) -> syn::Result { + let ident = input.parse()?; + let generics = input.parse()?; + + Ok(Self { ident, generics }) + } +} diff --git a/crates/cgp-macro-core/src/types/mod.rs b/crates/cgp-macro-core/src/types/mod.rs index 362f929c..166a4e6d 100644 --- a/crates/cgp-macro-core/src/types/mod.rs +++ b/crates/cgp-macro-core/src/types/mod.rs @@ -1,5 +1,6 @@ pub mod delegate_component; pub mod generics; +pub mod ident_type; pub mod keyword; pub mod keywords; pub mod namespace; From 3c64acb8938d975beb90b45fdf801478e0519d4f Mon Sep 17 00:00:00 2001 From: Soares Chen Date: Sat, 23 May 2026 22:22:12 +0200 Subject: [PATCH 52/81] Parsing new DelegateTable is working --- crates/cgp-macro-core/src/macros.rs | 2 +- crates/cgp-macro-lib/src/entrypoints/delegate_components.rs | 3 +++ crates/cgp-tests/tests/namespace.rs | 2 +- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/crates/cgp-macro-core/src/macros.rs b/crates/cgp-macro-core/src/macros.rs index 330613a8..fc68dc74 100644 --- a/crates/cgp-macro-core/src/macros.rs +++ b/crates/cgp-macro-core/src/macros.rs @@ -27,7 +27,7 @@ macro_rules! define_keyword { pub struct $struct_ident; impl $crate::traits::IsKeyword for $struct_ident { - const IDENT: &'static str = "open"; + const IDENT: &'static str = $value; } }; } diff --git a/crates/cgp-macro-lib/src/entrypoints/delegate_components.rs b/crates/cgp-macro-lib/src/entrypoints/delegate_components.rs index f595d9ac..3fcf47b1 100644 --- a/crates/cgp-macro-lib/src/entrypoints/delegate_components.rs +++ b/crates/cgp-macro-lib/src/entrypoints/delegate_components.rs @@ -1,3 +1,4 @@ +use cgp_macro_core::types::delegate_component::DelegateTable; use cgp_macro_core::types::generics::TypeGenerics; use cgp_macro_core::types::provider_struct::ProviderStruct; use proc_macro2::TokenStream; @@ -8,6 +9,8 @@ use crate::delegate_components::impl_delegate_components; use crate::parse::{DelegateComponents, SimpleType}; pub fn delegate_components(body: TokenStream) -> syn::Result { + let table: DelegateTable = parse2(body.clone())?; + let spec: DelegateComponents = parse2(body)?; let target_type = &spec.target_type; diff --git a/crates/cgp-tests/tests/namespace.rs b/crates/cgp-tests/tests/namespace.rs index 97b83ada..b26ea39f 100644 --- a/crates/cgp-tests/tests/namespace.rs +++ b/crates/cgp-tests/tests/namespace.rs @@ -1 +1 @@ -pub mod namespace_tests; +// pub mod namespace_tests; From d64d53f7b082dc22c341948576820473da9005a6 Mon Sep 17 00:00:00 2001 From: Soares Chen Date: Sat, 23 May 2026 22:30:32 +0200 Subject: [PATCH 53/81] New delegate_components! is working --- crates/cgp-core/src/lib.rs | 1 + crates/cgp-dispatch/Cargo.toml | 2 +- .../builders/build_and_merge_outputs.rs | 4 +-- .../field_builders/build_and_merge.rs | 4 +-- .../field_builders/build_and_set_field.rs | 2 +- .../providers/field_matchers/extract_field.rs | 2 +- .../field_matchers/extract_first_field.rs | 2 +- .../field_matchers/extract_handle.rs | 4 +-- .../providers/field_matchers/field_value.rs | 2 +- .../field_matchers/first_field_value.rs | 2 +- .../match_first_with_field_handlers.rs | 2 +- .../matchers/match_with_field_handlers.rs | 2 +- .../providers/matchers/to_field_handlers.rs | 2 +- .../with_handlers/build_with_handlers.rs | 2 +- .../match_first_with_handlers.rs | 2 +- .../match_first_with_handlers_mut.rs | 2 +- .../match_first_with_handlers_ref.rs | 2 +- .../with_handlers/match_with_handlers.rs | 4 +-- .../with_handlers/match_with_handlers_mut.rs | 4 +-- .../with_handlers/match_with_handlers_ref.rs | 4 +-- crates/cgp-handler/Cargo.toml | 2 +- .../src/components/async_computer.rs | 4 +-- crates/cgp-handler/src/components/computer.rs | 4 +-- crates/cgp-handler/src/components/handler.rs | 4 +-- crates/cgp-handler/src/components/produce.rs | 4 +-- .../cgp-handler/src/components/try_compute.rs | 4 +-- crates/cgp-handler/src/providers/compose.rs | 2 +- crates/cgp-handler/src/providers/pipe.rs | 2 +- crates/cgp-handler/src/providers/promote.rs | 2 +- .../cgp-handler/src/providers/promote_all.rs | 2 +- .../src/providers/promote_async.rs | 2 +- .../cgp-handler/src/providers/promote_ref.rs | 2 +- .../cgp-handler/src/providers/return_input.rs | 2 +- .../cgp-handler/src/providers/try_promote.rs | 2 +- .../types/delegate_component/entry/eval.rs | 2 +- .../types/delegate_component/table/main.rs | 13 ++++++++ .../src/entrypoints/delegate_components.rs | 32 ++----------------- crates/cgp-monad/Cargo.toml | 2 +- crates/cgp-monad/src/monadic/err.rs | 2 +- crates/cgp-monad/src/monadic/ok.rs | 2 +- .../cgp-monad/src/providers/pipe_monadic.rs | 4 +-- 41 files changed, 66 insertions(+), 80 deletions(-) diff --git a/crates/cgp-core/src/lib.rs b/crates/cgp-core/src/lib.rs index 549cce23..b9eeed7c 100644 --- a/crates/cgp-core/src/lib.rs +++ b/crates/cgp-core/src/lib.rs @@ -3,6 +3,7 @@ pub mod prelude; +pub use prelude as macro_prelude; #[doc(inline)] pub use { cgp_async_macro::async_trait, cgp_component as component, cgp_error as error, diff --git a/crates/cgp-dispatch/Cargo.toml b/crates/cgp-dispatch/Cargo.toml index ff0d9db1..75c8243a 100644 --- a/crates/cgp-dispatch/Cargo.toml +++ b/crates/cgp-dispatch/Cargo.toml @@ -10,6 +10,6 @@ keywords = { workspace = true } description = "Extensible data type dispatchers for CGP handlers" [dependencies] -cgp-core = { workspace = true } +cgp = { version = "0.7.0", path = "../cgp-core", package = "cgp-core" } cgp-monad = { workspace = true } cgp-handler = { workspace = true } diff --git a/crates/cgp-dispatch/src/providers/builders/build_and_merge_outputs.rs b/crates/cgp-dispatch/src/providers/builders/build_and_merge_outputs.rs index a5d6eed0..696152e1 100644 --- a/crates/cgp-dispatch/src/providers/builders/build_and_merge_outputs.rs +++ b/crates/cgp-dispatch/src/providers/builders/build_and_merge_outputs.rs @@ -1,5 +1,5 @@ -use cgp_core::field::traits::MapFields; -use cgp_core::prelude::*; +use cgp::field::traits::MapFields; +use cgp::prelude::*; use cgp_handler::{ ComputerComponent, ComputerRefComponent, HandlerComponent, HandlerRefComponent, TryComputerComponent, TryComputerRefComponent, diff --git a/crates/cgp-dispatch/src/providers/field_builders/build_and_merge.rs b/crates/cgp-dispatch/src/providers/field_builders/build_and_merge.rs index f44a422e..e440847d 100644 --- a/crates/cgp-dispatch/src/providers/field_builders/build_and_merge.rs +++ b/crates/cgp-dispatch/src/providers/field_builders/build_and_merge.rs @@ -1,5 +1,5 @@ -use cgp_core::field::impls::CanBuildFrom; -use cgp_core::prelude::*; +use cgp::field::impls::CanBuildFrom; +use cgp::prelude::*; use cgp_handler::{ Computer, ComputerComponent, Handler, HandlerComponent, TryComputer, TryComputerComponent, }; diff --git a/crates/cgp-dispatch/src/providers/field_builders/build_and_set_field.rs b/crates/cgp-dispatch/src/providers/field_builders/build_and_set_field.rs index fbb196e3..0532a8a9 100644 --- a/crates/cgp-dispatch/src/providers/field_builders/build_and_set_field.rs +++ b/crates/cgp-dispatch/src/providers/field_builders/build_and_set_field.rs @@ -1,4 +1,4 @@ -use cgp_core::prelude::*; +use cgp::prelude::*; use cgp_handler::{ Computer, ComputerComponent, Handler, HandlerComponent, TryComputer, TryComputerComponent, }; diff --git a/crates/cgp-dispatch/src/providers/field_matchers/extract_field.rs b/crates/cgp-dispatch/src/providers/field_matchers/extract_field.rs index 334f8ce1..05313bdb 100644 --- a/crates/cgp-dispatch/src/providers/field_matchers/extract_field.rs +++ b/crates/cgp-dispatch/src/providers/field_matchers/extract_field.rs @@ -1,4 +1,4 @@ -use cgp_core::prelude::*; +use cgp::prelude::*; use cgp_handler::{AsyncComputer, AsyncComputerComponent, Computer, ComputerComponent}; pub struct ExtractFieldAndHandle(pub PhantomData<(Tag, Provider)>); diff --git a/crates/cgp-dispatch/src/providers/field_matchers/extract_first_field.rs b/crates/cgp-dispatch/src/providers/field_matchers/extract_first_field.rs index 18c4f838..1fdab5f5 100644 --- a/crates/cgp-dispatch/src/providers/field_matchers/extract_first_field.rs +++ b/crates/cgp-dispatch/src/providers/field_matchers/extract_first_field.rs @@ -1,4 +1,4 @@ -use cgp_core::prelude::*; +use cgp::prelude::*; use cgp_handler::{AsyncComputer, AsyncComputerComponent, Computer, ComputerComponent}; pub struct ExtractFirstFieldAndHandle(pub PhantomData<(Tag, Provider)>); diff --git a/crates/cgp-dispatch/src/providers/field_matchers/extract_handle.rs b/crates/cgp-dispatch/src/providers/field_matchers/extract_handle.rs index 0b7d907e..a37d6a65 100644 --- a/crates/cgp-dispatch/src/providers/field_matchers/extract_handle.rs +++ b/crates/cgp-dispatch/src/providers/field_matchers/extract_handle.rs @@ -1,5 +1,5 @@ -use cgp_core::field::impls::CanDowncastFields; -use cgp_core::prelude::*; +use cgp::field::impls::CanDowncastFields; +use cgp::prelude::*; use cgp_handler::{AsyncComputer, AsyncComputerComponent, Computer, ComputerComponent}; pub struct DowncastAndHandle(pub PhantomData<(Input, Provider)>); diff --git a/crates/cgp-dispatch/src/providers/field_matchers/field_value.rs b/crates/cgp-dispatch/src/providers/field_matchers/field_value.rs index 9eef319a..191c957c 100644 --- a/crates/cgp-dispatch/src/providers/field_matchers/field_value.rs +++ b/crates/cgp-dispatch/src/providers/field_matchers/field_value.rs @@ -1,4 +1,4 @@ -use cgp_core::prelude::*; +use cgp::prelude::*; use cgp_handler::{AsyncComputer, AsyncComputerComponent, Computer, ComputerComponent}; pub struct HandleFieldValue(pub PhantomData); diff --git a/crates/cgp-dispatch/src/providers/field_matchers/first_field_value.rs b/crates/cgp-dispatch/src/providers/field_matchers/first_field_value.rs index 899e955c..074fde06 100644 --- a/crates/cgp-dispatch/src/providers/field_matchers/first_field_value.rs +++ b/crates/cgp-dispatch/src/providers/field_matchers/first_field_value.rs @@ -1,4 +1,4 @@ -use cgp_core::prelude::*; +use cgp::prelude::*; use cgp_handler::{AsyncComputer, AsyncComputerComponent, Computer, ComputerComponent}; pub struct HandleFirstFieldValue(pub PhantomData); diff --git a/crates/cgp-dispatch/src/providers/matchers/match_first_with_field_handlers.rs b/crates/cgp-dispatch/src/providers/matchers/match_first_with_field_handlers.rs index 1fe4cea6..51f12599 100644 --- a/crates/cgp-dispatch/src/providers/matchers/match_first_with_field_handlers.rs +++ b/crates/cgp-dispatch/src/providers/matchers/match_first_with_field_handlers.rs @@ -1,4 +1,4 @@ -use cgp_core::prelude::*; +use cgp::prelude::*; use cgp_handler::UseInputDelegate; use crate::providers::matchers::to_field_handlers::{ diff --git a/crates/cgp-dispatch/src/providers/matchers/match_with_field_handlers.rs b/crates/cgp-dispatch/src/providers/matchers/match_with_field_handlers.rs index fd9089e1..087f8afe 100644 --- a/crates/cgp-dispatch/src/providers/matchers/match_with_field_handlers.rs +++ b/crates/cgp-dispatch/src/providers/matchers/match_with_field_handlers.rs @@ -1,4 +1,4 @@ -use cgp_core::prelude::*; +use cgp::prelude::*; use cgp_handler::{ AsyncComputerComponent, AsyncComputerRefComponent, ComputerComponent, ComputerRefComponent, HandlerComponent, HandlerRefComponent, PromoteRef, TryComputerComponent, diff --git a/crates/cgp-dispatch/src/providers/matchers/to_field_handlers.rs b/crates/cgp-dispatch/src/providers/matchers/to_field_handlers.rs index 79c1546c..29f4d78d 100644 --- a/crates/cgp-dispatch/src/providers/matchers/to_field_handlers.rs +++ b/crates/cgp-dispatch/src/providers/matchers/to_field_handlers.rs @@ -1,4 +1,4 @@ -use cgp_core::prelude::*; +use cgp::prelude::*; use crate::{ExtractFieldAndHandle, ExtractFirstFieldAndHandle}; diff --git a/crates/cgp-dispatch/src/providers/with_handlers/build_with_handlers.rs b/crates/cgp-dispatch/src/providers/with_handlers/build_with_handlers.rs index 73d9f583..081aaae4 100644 --- a/crates/cgp-dispatch/src/providers/with_handlers/build_with_handlers.rs +++ b/crates/cgp-dispatch/src/providers/with_handlers/build_with_handlers.rs @@ -1,4 +1,4 @@ -use cgp_core::prelude::*; +use cgp::prelude::*; use cgp_handler::{ Computer, ComputerComponent, Handler, HandlerComponent, PipeHandlers, TryComputer, TryComputerComponent, diff --git a/crates/cgp-dispatch/src/providers/with_handlers/match_first_with_handlers.rs b/crates/cgp-dispatch/src/providers/with_handlers/match_first_with_handlers.rs index e7384169..fe068031 100644 --- a/crates/cgp-dispatch/src/providers/with_handlers/match_first_with_handlers.rs +++ b/crates/cgp-dispatch/src/providers/with_handlers/match_first_with_handlers.rs @@ -1,6 +1,6 @@ use core::marker::PhantomData; -use cgp_core::prelude::*; +use cgp::prelude::*; use cgp_handler::{AsyncComputer, AsyncComputerComponent, Computer, ComputerComponent}; use crate::DispatchMatchers; diff --git a/crates/cgp-dispatch/src/providers/with_handlers/match_first_with_handlers_mut.rs b/crates/cgp-dispatch/src/providers/with_handlers/match_first_with_handlers_mut.rs index 7b351916..89f93988 100644 --- a/crates/cgp-dispatch/src/providers/with_handlers/match_first_with_handlers_mut.rs +++ b/crates/cgp-dispatch/src/providers/with_handlers/match_first_with_handlers_mut.rs @@ -1,6 +1,6 @@ use core::marker::PhantomData; -use cgp_core::prelude::*; +use cgp::prelude::*; use cgp_handler::{AsyncComputer, AsyncComputerComponent, Computer, ComputerComponent}; use crate::DispatchMatchers; diff --git a/crates/cgp-dispatch/src/providers/with_handlers/match_first_with_handlers_ref.rs b/crates/cgp-dispatch/src/providers/with_handlers/match_first_with_handlers_ref.rs index 9c869999..c1c2e330 100644 --- a/crates/cgp-dispatch/src/providers/with_handlers/match_first_with_handlers_ref.rs +++ b/crates/cgp-dispatch/src/providers/with_handlers/match_first_with_handlers_ref.rs @@ -1,6 +1,6 @@ use core::marker::PhantomData; -use cgp_core::prelude::*; +use cgp::prelude::*; use cgp_handler::{AsyncComputer, AsyncComputerComponent, Computer, ComputerComponent}; use crate::DispatchMatchers; diff --git a/crates/cgp-dispatch/src/providers/with_handlers/match_with_handlers.rs b/crates/cgp-dispatch/src/providers/with_handlers/match_with_handlers.rs index f2ae5ef6..75fecc44 100644 --- a/crates/cgp-dispatch/src/providers/with_handlers/match_with_handlers.rs +++ b/crates/cgp-dispatch/src/providers/with_handlers/match_with_handlers.rs @@ -1,7 +1,7 @@ use core::marker::PhantomData; -use cgp_core::field::traits::FinalizeExtractResult; -use cgp_core::prelude::*; +use cgp::field::traits::FinalizeExtractResult; +use cgp::prelude::*; use cgp_handler::{AsyncComputer, AsyncComputerComponent, Computer, ComputerComponent}; use crate::DispatchMatchers; diff --git a/crates/cgp-dispatch/src/providers/with_handlers/match_with_handlers_mut.rs b/crates/cgp-dispatch/src/providers/with_handlers/match_with_handlers_mut.rs index 01e6100b..a0ef403b 100644 --- a/crates/cgp-dispatch/src/providers/with_handlers/match_with_handlers_mut.rs +++ b/crates/cgp-dispatch/src/providers/with_handlers/match_with_handlers_mut.rs @@ -1,7 +1,7 @@ use core::marker::PhantomData; -use cgp_core::field::traits::FinalizeExtractResult; -use cgp_core::prelude::*; +use cgp::field::traits::FinalizeExtractResult; +use cgp::prelude::*; use cgp_handler::{AsyncComputer, AsyncComputerComponent, Computer, ComputerComponent}; use crate::DispatchMatchers; diff --git a/crates/cgp-dispatch/src/providers/with_handlers/match_with_handlers_ref.rs b/crates/cgp-dispatch/src/providers/with_handlers/match_with_handlers_ref.rs index 07c08f91..5a98f62e 100644 --- a/crates/cgp-dispatch/src/providers/with_handlers/match_with_handlers_ref.rs +++ b/crates/cgp-dispatch/src/providers/with_handlers/match_with_handlers_ref.rs @@ -1,7 +1,7 @@ use core::marker::PhantomData; -use cgp_core::field::traits::FinalizeExtractResult; -use cgp_core::prelude::*; +use cgp::field::traits::FinalizeExtractResult; +use cgp::prelude::*; use cgp_handler::{AsyncComputer, AsyncComputerComponent, Computer, ComputerComponent}; use crate::DispatchMatchers; diff --git a/crates/cgp-handler/Cargo.toml b/crates/cgp-handler/Cargo.toml index 07247c75..7d61e121 100644 --- a/crates/cgp-handler/Cargo.toml +++ b/crates/cgp-handler/Cargo.toml @@ -10,4 +10,4 @@ keywords = { workspace = true } description = "Generalized handler interfaces for functional programming" [dependencies] -cgp-core = { workspace = true } +cgp = { version = "0.7.0", path = "../cgp-core", package = "cgp-core" } diff --git a/crates/cgp-handler/src/components/async_computer.rs b/crates/cgp-handler/src/components/async_computer.rs index 8b385641..3e58a4f4 100644 --- a/crates/cgp-handler/src/components/async_computer.rs +++ b/crates/cgp-handler/src/components/async_computer.rs @@ -1,7 +1,7 @@ use core::marker::PhantomData; -use cgp_core::component::UseDelegate; -use cgp_core::prelude::*; +use cgp::component::UseDelegate; +use cgp::prelude::*; use crate::UseInputDelegate; diff --git a/crates/cgp-handler/src/components/computer.rs b/crates/cgp-handler/src/components/computer.rs index d2ba0f0d..8d971f9f 100644 --- a/crates/cgp-handler/src/components/computer.rs +++ b/crates/cgp-handler/src/components/computer.rs @@ -1,7 +1,7 @@ use core::marker::PhantomData; -use cgp_core::component::UseDelegate; -use cgp_core::prelude::*; +use cgp::component::UseDelegate; +use cgp::prelude::*; use crate::UseInputDelegate; diff --git a/crates/cgp-handler/src/components/handler.rs b/crates/cgp-handler/src/components/handler.rs index aed0a397..098815e9 100644 --- a/crates/cgp-handler/src/components/handler.rs +++ b/crates/cgp-handler/src/components/handler.rs @@ -1,7 +1,7 @@ use core::marker::PhantomData; -use cgp_core::component::UseDelegate; -use cgp_core::prelude::*; +use cgp::component::UseDelegate; +use cgp::prelude::*; use crate::UseInputDelegate; diff --git a/crates/cgp-handler/src/components/produce.rs b/crates/cgp-handler/src/components/produce.rs index 9f81158d..4dc88db1 100644 --- a/crates/cgp-handler/src/components/produce.rs +++ b/crates/cgp-handler/src/components/produce.rs @@ -1,7 +1,7 @@ use core::marker::PhantomData; -use cgp_core::component::UseDelegate; -use cgp_core::prelude::*; +use cgp::component::UseDelegate; +use cgp::prelude::*; #[cgp_component { provider: Producer, diff --git a/crates/cgp-handler/src/components/try_compute.rs b/crates/cgp-handler/src/components/try_compute.rs index dec02530..75b970b6 100644 --- a/crates/cgp-handler/src/components/try_compute.rs +++ b/crates/cgp-handler/src/components/try_compute.rs @@ -1,7 +1,7 @@ use core::marker::PhantomData; -use cgp_core::component::UseDelegate; -use cgp_core::prelude::*; +use cgp::component::UseDelegate; +use cgp::prelude::*; use crate::UseInputDelegate; diff --git a/crates/cgp-handler/src/providers/compose.rs b/crates/cgp-handler/src/providers/compose.rs index a8a4918b..262a1e4b 100644 --- a/crates/cgp-handler/src/providers/compose.rs +++ b/crates/cgp-handler/src/providers/compose.rs @@ -1,4 +1,4 @@ -use cgp_core::prelude::*; +use cgp::prelude::*; use crate::{ AsyncComputer, AsyncComputerComponent, Computer, ComputerComponent, Handler, HandlerComponent, diff --git a/crates/cgp-handler/src/providers/pipe.rs b/crates/cgp-handler/src/providers/pipe.rs index 4a368b16..7c9c4df4 100644 --- a/crates/cgp-handler/src/providers/pipe.rs +++ b/crates/cgp-handler/src/providers/pipe.rs @@ -1,6 +1,6 @@ use core::marker::PhantomData; -use cgp_core::prelude::*; +use cgp::prelude::*; use crate::ComposeHandlers; diff --git a/crates/cgp-handler/src/providers/promote.rs b/crates/cgp-handler/src/providers/promote.rs index 8e8427c0..46dd2ab4 100644 --- a/crates/cgp-handler/src/providers/promote.rs +++ b/crates/cgp-handler/src/providers/promote.rs @@ -1,4 +1,4 @@ -use cgp_core::prelude::*; +use cgp::prelude::*; use crate::{ AsyncComputer, Computer, ComputerComponent, Handler, HandlerComponent, Producer, TryComputer, diff --git a/crates/cgp-handler/src/providers/promote_all.rs b/crates/cgp-handler/src/providers/promote_all.rs index f302388a..5c4472cf 100644 --- a/crates/cgp-handler/src/providers/promote_all.rs +++ b/crates/cgp-handler/src/providers/promote_all.rs @@ -1,4 +1,4 @@ -use cgp_core::prelude::*; +use cgp::prelude::*; use crate::{ AsyncComputerComponent, AsyncComputerRefComponent, ComputerComponent, ComputerRefComponent, diff --git a/crates/cgp-handler/src/providers/promote_async.rs b/crates/cgp-handler/src/providers/promote_async.rs index 7392a0f1..cbe2cfb7 100644 --- a/crates/cgp-handler/src/providers/promote_async.rs +++ b/crates/cgp-handler/src/providers/promote_async.rs @@ -1,4 +1,4 @@ -use cgp_core::prelude::*; +use cgp::prelude::*; use crate::{ AsyncComputer, AsyncComputerComponent, Computer, Handler, HandlerComponent, TryComputer, diff --git a/crates/cgp-handler/src/providers/promote_ref.rs b/crates/cgp-handler/src/providers/promote_ref.rs index 2b8619ac..92e76ffb 100644 --- a/crates/cgp-handler/src/providers/promote_ref.rs +++ b/crates/cgp-handler/src/providers/promote_ref.rs @@ -1,6 +1,6 @@ use core::ops::Deref; -use cgp_core::prelude::*; +use cgp::prelude::*; use crate::{ AsyncComputer, AsyncComputerComponent, AsyncComputerRef, AsyncComputerRefComponent, Computer, diff --git a/crates/cgp-handler/src/providers/return_input.rs b/crates/cgp-handler/src/providers/return_input.rs index 0ff28e87..a7d542d7 100644 --- a/crates/cgp-handler/src/providers/return_input.rs +++ b/crates/cgp-handler/src/providers/return_input.rs @@ -1,4 +1,4 @@ -use cgp_core::prelude::*; +use cgp::prelude::*; use crate::{ AsyncComputer, AsyncComputerComponent, Computer, ComputerComponent, Handler, HandlerComponent, diff --git a/crates/cgp-handler/src/providers/try_promote.rs b/crates/cgp-handler/src/providers/try_promote.rs index 99938621..39de548a 100644 --- a/crates/cgp-handler/src/providers/try_promote.rs +++ b/crates/cgp-handler/src/providers/try_promote.rs @@ -1,4 +1,4 @@ -use cgp_core::prelude::*; +use cgp::prelude::*; use crate::{ AsyncComputer, AsyncComputerComponent, Computer, ComputerComponent, Handler, HandlerComponent, diff --git a/crates/cgp-macro-core/src/types/delegate_component/entry/eval.rs b/crates/cgp-macro-core/src/types/delegate_component/entry/eval.rs index 9407b822..28d570b4 100644 --- a/crates/cgp-macro-core/src/types/delegate_component/entry/eval.rs +++ b/crates/cgp-macro-core/src/types/delegate_component/entry/eval.rs @@ -52,7 +52,7 @@ impl EvaluatedDelegateEntry { generics.params.push(parse_quote!(__Params__)); generics.make_where_clause().predicates.push(parse_quote! { - #value: #IsProviderFor<#key, __Context__, __Params__>, + #value: #IsProviderFor<#key, __Context__, __Params__> }); let (impl_generics, _, where_clause) = generics.split_for_impl(); diff --git a/crates/cgp-macro-core/src/types/delegate_component/table/main.rs b/crates/cgp-macro-core/src/types/delegate_component/table/main.rs index a887e4e4..6a5bb9db 100644 --- a/crates/cgp-macro-core/src/types/delegate_component/table/main.rs +++ b/crates/cgp-macro-core/src/types/delegate_component/table/main.rs @@ -1,3 +1,4 @@ +use proc_macro2::TokenStream; use quote::ToTokens; use syn::parse::{Parse, ParseStream}; use syn::{ItemImpl, ItemStruct, Type, braced, parse2}; @@ -85,3 +86,15 @@ impl DelegateTable { }) } } + +impl ToTokens for EvaluatedDelegateTable { + fn to_tokens(&self, tokens: &mut TokenStream) { + for item_struct in &self.item_structs { + item_struct.to_tokens(tokens); + } + + for item_impl in &self.item_impls { + item_impl.to_tokens(tokens); + } + } +} diff --git a/crates/cgp-macro-lib/src/entrypoints/delegate_components.rs b/crates/cgp-macro-lib/src/entrypoints/delegate_components.rs index 3fcf47b1..ba10cd0e 100644 --- a/crates/cgp-macro-lib/src/entrypoints/delegate_components.rs +++ b/crates/cgp-macro-lib/src/entrypoints/delegate_components.rs @@ -1,40 +1,12 @@ use cgp_macro_core::types::delegate_component::DelegateTable; -use cgp_macro_core::types::generics::TypeGenerics; -use cgp_macro_core::types::provider_struct::ProviderStruct; use proc_macro2::TokenStream; use quote::ToTokens; use syn::parse2; -use crate::delegate_components::impl_delegate_components; -use crate::parse::{DelegateComponents, SimpleType}; - pub fn delegate_components(body: TokenStream) -> syn::Result { let table: DelegateTable = parse2(body.clone())?; - let spec: DelegateComponents = parse2(body)?; - - let target_type = &spec.target_type; - let target_generics = &spec.target_generics; - - let mut output = TokenStream::new(); - - if spec.new_struct { - let target_type: SimpleType = parse2(target_type.to_token_stream())?; - - let type_generics = target_type.generics.unwrap_or_default().generics; - - let component_struct = ProviderStruct { - ident: target_type.name, - generics: type_generics, - } - .to_item_struct()?; - - output.extend(component_struct.to_token_stream()); - } - - let impl_items = impl_delegate_components(target_type, target_generics, &spec.entries)?; - - output.extend(impl_items); + let evaluated_table = table.eval()?; - Ok(output) + Ok(evaluated_table.to_token_stream()) } diff --git a/crates/cgp-monad/Cargo.toml b/crates/cgp-monad/Cargo.toml index 558b5ab3..2de784d6 100644 --- a/crates/cgp-monad/Cargo.toml +++ b/crates/cgp-monad/Cargo.toml @@ -10,5 +10,5 @@ keywords = { workspace = true } description = "Monadic constructs for CGP computation" [dependencies] -cgp-core = { workspace = true } +cgp = { version = "0.7.0", path = "../cgp-core", package = "cgp-core" } cgp-handler = { workspace = true } diff --git a/crates/cgp-monad/src/monadic/err.rs b/crates/cgp-monad/src/monadic/err.rs index f080b77a..3beea7d5 100644 --- a/crates/cgp-monad/src/monadic/err.rs +++ b/crates/cgp-monad/src/monadic/err.rs @@ -1,4 +1,4 @@ -use cgp_core::prelude::*; +use cgp::prelude::*; use cgp_handler::{AsyncComputer, AsyncComputerComponent, Computer, ComputerComponent}; use crate::monadic::ident::IdentMonadic; diff --git a/crates/cgp-monad/src/monadic/ok.rs b/crates/cgp-monad/src/monadic/ok.rs index c90dba65..d8bfdf4f 100644 --- a/crates/cgp-monad/src/monadic/ok.rs +++ b/crates/cgp-monad/src/monadic/ok.rs @@ -1,4 +1,4 @@ -use cgp_core::prelude::*; +use cgp::prelude::*; use cgp_handler::{AsyncComputer, AsyncComputerComponent, Computer, ComputerComponent}; use crate::monadic::ident::IdentMonadic; diff --git a/crates/cgp-monad/src/providers/pipe_monadic.rs b/crates/cgp-monad/src/providers/pipe_monadic.rs index da2c81b6..eff049ad 100644 --- a/crates/cgp-monad/src/providers/pipe_monadic.rs +++ b/crates/cgp-monad/src/providers/pipe_monadic.rs @@ -1,5 +1,5 @@ -use cgp_core::field::traits::MapFields; -use cgp_core::prelude::*; +use cgp::field::traits::MapFields; +use cgp::prelude::*; use cgp_handler::{ AsyncComputerComponent, ComposeHandlers, ComputerComponent, HandlerComponent, TryComputerComponent, TryPromote, From 444d83265cfac9c634d183bcafa024cbe0e9cc23 Mon Sep 17 00:00:00 2001 From: Soares Chen Date: Sat, 23 May 2026 22:34:47 +0200 Subject: [PATCH 54/81] Fixing namespace expansion --- crates/cgp-tests/tests/namespace.rs | 2 +- crates/cgp-tests/tests/namespace_tests/multi_param.rs | 4 ++-- crates/cgp-tests/tests/namespace_tests/namespace.rs | 2 +- .../cgp-tests/tests/namespace_tests/namespace_macro/basic.rs | 2 +- .../tests/namespace_tests/namespace_macro/default_generics.rs | 2 +- .../namespace_tests/namespace_macro/extended_namespace.rs | 2 +- .../tests/namespace_tests/namespace_macro/multi_namespace.rs | 2 +- .../tests/namespace_tests/namespace_macro/symbol_path.rs | 2 +- .../tests/namespace_tests/namespace_macro/type_path.rs | 2 +- crates/cgp-tests/tests/namespace_tests/open.rs | 2 +- crates/cgp-tests/tests/namespace_tests/redirect.rs | 2 +- 11 files changed, 12 insertions(+), 12 deletions(-) diff --git a/crates/cgp-tests/tests/namespace.rs b/crates/cgp-tests/tests/namespace.rs index b26ea39f..97b83ada 100644 --- a/crates/cgp-tests/tests/namespace.rs +++ b/crates/cgp-tests/tests/namespace.rs @@ -1 +1 @@ -// pub mod namespace_tests; +pub mod namespace_tests; diff --git a/crates/cgp-tests/tests/namespace_tests/multi_param.rs b/crates/cgp-tests/tests/namespace_tests/multi_param.rs index a1f37460..f6290bc8 100644 --- a/crates/cgp-tests/tests/namespace_tests/multi_param.rs +++ b/crates/cgp-tests/tests/namespace_tests/multi_param.rs @@ -15,7 +15,7 @@ pub struct AppA; delegate_components! { AppA { - open FooProviderComponent; + open {FooProviderComponent}, @FooProviderComponent.String.u32: DummyFoo, @@ -39,7 +39,7 @@ pub struct AppB; delegate_components! { AppB { - namespace default; + namespace default, @app.FooProviderComponent.String.u64: DummyFoo, diff --git a/crates/cgp-tests/tests/namespace_tests/namespace.rs b/crates/cgp-tests/tests/namespace_tests/namespace.rs index a16834a5..ea272b36 100644 --- a/crates/cgp-tests/tests/namespace_tests/namespace.rs +++ b/crates/cgp-tests/tests/namespace_tests/namespace.rs @@ -14,7 +14,7 @@ pub struct App; delegate_components! { App { - namespace default; + namespace default, @cgp.core.error.ErrorTypeProviderComponent: UseType, diff --git a/crates/cgp-tests/tests/namespace_tests/namespace_macro/basic.rs b/crates/cgp-tests/tests/namespace_tests/namespace_macro/basic.rs index 4e4d23b0..3e06ef62 100644 --- a/crates/cgp-tests/tests/namespace_tests/namespace_macro/basic.rs +++ b/crates/cgp-tests/tests/namespace_tests/namespace_macro/basic.rs @@ -35,7 +35,7 @@ pub struct App; delegate_components! { App { - namespace MyNamespace; + namespace MyNamespace, @MyFooComponent: DummyFoo, diff --git a/crates/cgp-tests/tests/namespace_tests/namespace_macro/default_generics.rs b/crates/cgp-tests/tests/namespace_tests/namespace_macro/default_generics.rs index b23f5c68..ba794217 100644 --- a/crates/cgp-tests/tests/namespace_tests/namespace_macro/default_generics.rs +++ b/crates/cgp-tests/tests/namespace_tests/namespace_macro/default_generics.rs @@ -6,7 +6,7 @@ pub struct App; delegate_components! { App { - namespace default; + namespace default, @test.ShowImplComponent.u64: ShowWithDisplay, diff --git a/crates/cgp-tests/tests/namespace_tests/namespace_macro/extended_namespace.rs b/crates/cgp-tests/tests/namespace_tests/namespace_macro/extended_namespace.rs index 64d08afb..64fe931c 100644 --- a/crates/cgp-tests/tests/namespace_tests/namespace_macro/extended_namespace.rs +++ b/crates/cgp-tests/tests/namespace_tests/namespace_macro/extended_namespace.rs @@ -8,7 +8,7 @@ pub struct App; delegate_components! { App { - namespace ExtendedNamespace; + namespace ExtendedNamespace, @app.ErrorTypeProviderComponent: UseType, diff --git a/crates/cgp-tests/tests/namespace_tests/namespace_macro/multi_namespace.rs b/crates/cgp-tests/tests/namespace_tests/namespace_macro/multi_namespace.rs index 199bfa0a..df840a83 100644 --- a/crates/cgp-tests/tests/namespace_tests/namespace_macro/multi_namespace.rs +++ b/crates/cgp-tests/tests/namespace_tests/namespace_macro/multi_namespace.rs @@ -46,7 +46,7 @@ pub struct App; delegate_components! { App { - namespace MyNamespace; + namespace MyNamespace, @MyApp.MyFooComponent: DummyFoo, diff --git a/crates/cgp-tests/tests/namespace_tests/namespace_macro/symbol_path.rs b/crates/cgp-tests/tests/namespace_tests/namespace_macro/symbol_path.rs index b840bea4..7c88819f 100644 --- a/crates/cgp-tests/tests/namespace_tests/namespace_macro/symbol_path.rs +++ b/crates/cgp-tests/tests/namespace_tests/namespace_macro/symbol_path.rs @@ -36,7 +36,7 @@ pub struct App; delegate_components! { App { - namespace MyNamespace; + namespace MyNamespace, @my_app.MyFooComponent: DummyFoo, diff --git a/crates/cgp-tests/tests/namespace_tests/namespace_macro/type_path.rs b/crates/cgp-tests/tests/namespace_tests/namespace_macro/type_path.rs index bdf477e5..748e0630 100644 --- a/crates/cgp-tests/tests/namespace_tests/namespace_macro/type_path.rs +++ b/crates/cgp-tests/tests/namespace_tests/namespace_macro/type_path.rs @@ -38,7 +38,7 @@ pub struct App; delegate_components! { App { - namespace MyNamespace; + namespace MyNamespace, @MyApp.MyFooComponent: DummyFoo, diff --git a/crates/cgp-tests/tests/namespace_tests/open.rs b/crates/cgp-tests/tests/namespace_tests/open.rs index 61b6aa2c..68afae36 100644 --- a/crates/cgp-tests/tests/namespace_tests/open.rs +++ b/crates/cgp-tests/tests/namespace_tests/open.rs @@ -24,7 +24,7 @@ impl BarProvider { delegate_components! { App { - open FooProviderComponent, BarProviderComponent; + open {FooProviderComponent, BarProviderComponent}, @FooProviderComponent.String: DummyFoo, diff --git a/crates/cgp-tests/tests/namespace_tests/redirect.rs b/crates/cgp-tests/tests/namespace_tests/redirect.rs index d86dbf45..9d3b2bc0 100644 --- a/crates/cgp-tests/tests/namespace_tests/redirect.rs +++ b/crates/cgp-tests/tests/namespace_tests/redirect.rs @@ -19,7 +19,7 @@ pub struct App; delegate_components! { App { - namespace default; + namespace default, // @bar: TestProvider, From 9d56a847d15b98e8872696d5d151caa2a65bac02 Mon Sep 17 00:00:00 2001 From: Soares Chen Date: Sat, 23 May 2026 22:41:09 +0200 Subject: [PATCH 55/81] Fixed namespace expansion --- .../src/types/delegate_component/key/path.rs | 11 +++++++---- .../namespace_macro/multi_namespace.rs | 2 +- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/crates/cgp-macro-core/src/types/delegate_component/key/path.rs b/crates/cgp-macro-core/src/types/delegate_component/key/path.rs index 32e645c0..9bd71af0 100644 --- a/crates/cgp-macro-core/src/types/delegate_component/key/path.rs +++ b/crates/cgp-macro-core/src/types/delegate_component/key/path.rs @@ -1,6 +1,6 @@ use syn::parse::{Parse, ParseStream}; +use syn::parse_quote; use syn::token::At; -use syn::{Type, parse_quote}; use crate::functions::merge_generics; use crate::types::delegate_component::{EvalDelegateKey, EvaluatedDelegateKey}; @@ -31,12 +31,15 @@ impl EvalDelegateKey for PathDelegateKey { let mut keys = Vec::new(); for (inner_generics, path) in paths { - let generics = merge_generics(outer_generics, &inner_generics); - let path_type: Type = parse_quote!(#path); + let mut generics = merge_generics(outer_generics, &inner_generics); + generics.params.push(parse_quote!(__Wildcard__)); + + let prefix = path.to_prefix(parse_quote!(__Wildcard__)); + let key_type = parse_quote!(#prefix); let key = EvaluatedDelegateKey { generics, - key: path_type, + key: key_type, }; keys.push(key) diff --git a/crates/cgp-tests/tests/namespace_tests/namespace_macro/multi_namespace.rs b/crates/cgp-tests/tests/namespace_tests/namespace_macro/multi_namespace.rs index df840a83..4fef0421 100644 --- a/crates/cgp-tests/tests/namespace_tests/namespace_macro/multi_namespace.rs +++ b/crates/cgp-tests/tests/namespace_tests/namespace_macro/multi_namespace.rs @@ -66,7 +66,7 @@ pub struct OtherApp; delegate_components! { OtherApp { - namespace OtherNamespace; + namespace OtherNamespace, @my_app.MyFooComponent: DummyFoo, From 06ee26b953589df85416a0bf617b91dca025a1a6 Mon Sep 17 00:00:00 2001 From: Soares Chen Date: Sat, 23 May 2026 22:42:10 +0200 Subject: [PATCH 56/81] Remove old DelegateComponent constructs --- .../src/parse/delegate_components.rs | 130 +----------------- 1 file changed, 3 insertions(+), 127 deletions(-) diff --git a/crates/cgp-macro-lib/src/parse/delegate_components.rs b/crates/cgp-macro-lib/src/parse/delegate_components.rs index 97b19f8d..e3c25f4c 100644 --- a/crates/cgp-macro-lib/src/parse/delegate_components.rs +++ b/crates/cgp-macro-lib/src/parse/delegate_components.rs @@ -2,23 +2,16 @@ use core::iter; use cgp_macro_core::functions::merge_generics; use cgp_macro_core::types::generics::{ImplGenerics, TypeGenerics}; -use proc_macro2::{Span, TokenStream}; +use proc_macro2::TokenStream; use quote::{ToTokens, TokenStreamExt, quote}; use syn::parse::discouraged::Speculative; use syn::parse::{Parse, ParseStream}; use syn::punctuated::Punctuated; -use syn::token::{At, Bracket, Colon, Comma, Gt, Lt, RArrow, Semi}; -use syn::{Error, Generics, Ident, Token, Type, braced, bracketed, parse_quote, parse2}; +use syn::token::{At, Bracket, Colon, Comma, Gt, Lt, RArrow}; +use syn::{Error, Generics, Ident, Token, Type, braced, bracketed, parse_quote}; use crate::parse::{ComponentPaths, SimpleType}; -pub struct DelegateComponents { - pub new_struct: bool, - pub target_type: Type, - pub target_generics: ImplGenerics, - pub entries: Punctuated, Comma>, -} - #[derive(Clone)] pub struct DelegateEntry { pub keys: Punctuated, Comma>, @@ -71,123 +64,6 @@ impl DelegateValue { } } -impl Parse for DelegateComponents { - fn parse(input: ParseStream) -> syn::Result { - let target_generics = if input.peek(Lt) { - input.parse()? - } else { - Default::default() - }; - - let new_struct = { - let fork = input.fork(); - let new_ident: Option = fork.parse().ok(); - match new_ident { - Some(new_ident) if new_ident == "new" => { - input.advance_to(&fork); - true - } - _ => false, - } - }; - - let target_type: Type = input.parse()?; - - let content; - braced!(content in input); - - let meta_entries = parse_meta_delegate_entries(&content, &target_type)?; - - let delegate_entries: Punctuated, Comma> = - Punctuated::parse_terminated(&content)?; - - let entries = meta_entries.into_iter().chain(delegate_entries).collect(); - - Ok(Self { - new_struct, - target_type, - target_generics, - entries, - }) - } -} - -pub fn parse_meta_delegate_entries( - input: ParseStream, - target_type: &Type, -) -> syn::Result>> { - let mut entries = Vec::new(); - - while input.peek(Ident) { - let fork = input.fork(); - let keyword: Ident = fork.parse()?; - - if keyword == "open" { - input.advance_to(&fork); - - let components: Punctuated = Punctuated::parse_separated_nonempty(input)?; - let _: Semi = input.parse()?; - - for component in components { - let value = DelegateValue::Type(parse2( - quote!(RedirectLookup<#target_type, PathCons<#component, ε>>), - )?); - - let key = DelegateKey { - ty: component, - generics: Default::default(), - }; - - let entry = DelegateEntry { - keys: Punctuated::from_iter([key]), - mode: DelegateMode::Provider(Colon(Span::call_site())), - value, - }; - - entries.push(entry) - } - } else if keyword == "namespace" { - input.advance_to(&fork); - - let ident: Ident = input.parse()?; - let _: Semi = input.parse()?; - - let namespace_ident = if ident == "default" { - Ident::new("DefaultNamespace", ident.span()) - } else { - ident - }; - - let delegate_key: Type = parse2(quote! { - __Component__ - })?; - - let generics: ImplGenerics = parse2(quote! { - <__Component__: #namespace_ident< #target_type >> - })?; - - let delegate_value: Type = parse2(quote! { - < __Component__ as #namespace_ident< #target_type >>::Provider - })?; - - let entry = DelegateEntry { - keys: Punctuated::from_iter([DelegateKey { - ty: delegate_key, - generics, - }]), - mode: DelegateMode::Provider(Colon(Span::call_site())), - value: DelegateValue::Type(delegate_value), - }; - - entries.push(entry) - } else { - break; - } - } - - Ok(entries) -} - impl Parse for DelegateEntry { fn parse(input: ParseStream) -> syn::Result { let components = if input.peek(Bracket) { From a060e3f87cc335513df6acd8bc431aafa3c6ad1a Mon Sep 17 00:00:00 2001 From: Soares Chen Date: Sun, 24 May 2026 20:59:43 +0200 Subject: [PATCH 57/81] Use back semicolon for delegate statements --- .../src/types/delegate_component/entries.rs | 43 ++++++++++++++----- .../entry/{combined.rs => mapping.rs} | 0 .../src/types/delegate_component/entry/mod.rs | 6 ++- .../delegate_component/entry/namespace.rs | 9 +++- .../types/delegate_component/entry/open.rs | 11 ++++- .../delegate_component/entry/statement.rs | 37 ++++++++++++++++ .../tests/namespace_tests/multi_param.rs | 4 +- .../tests/namespace_tests/namespace.rs | 2 +- .../namespace_tests/namespace_macro/basic.rs | 2 +- .../namespace_macro/default_generics.rs | 2 +- .../namespace_macro/extended_namespace.rs | 2 +- .../namespace_macro/multi_namespace.rs | 4 +- .../namespace_macro/symbol_path.rs | 2 +- .../namespace_macro/type_path.rs | 2 +- .../cgp-tests/tests/namespace_tests/open.rs | 2 +- .../tests/namespace_tests/redirect.rs | 2 +- 16 files changed, 102 insertions(+), 28 deletions(-) rename crates/cgp-macro-core/src/types/delegate_component/entry/{combined.rs => mapping.rs} (100%) create mode 100644 crates/cgp-macro-core/src/types/delegate_component/entry/statement.rs diff --git a/crates/cgp-macro-core/src/types/delegate_component/entries.rs b/crates/cgp-macro-core/src/types/delegate_component/entries.rs index 47f8e904..7f7c34ab 100644 --- a/crates/cgp-macro-core/src/types/delegate_component/entries.rs +++ b/crates/cgp-macro-core/src/types/delegate_component/entries.rs @@ -1,21 +1,37 @@ +use syn::parse::discouraged::Speculative; use syn::parse::{Parse, ParseStream}; use syn::punctuated::Punctuated; use syn::token::Comma; use syn::{Generics, ItemImpl, Type}; use crate::types::delegate_component::{ - DelegateEntry, EvalDelegateEntry, ExtractInnerDelegateTables, InnerDelegateTable, + DelegateEntry, DelegateStatement, EvalDelegateEntry, ExtractInnerDelegateTables, + InnerDelegateTable, }; #[derive(Debug, Clone)] pub struct DelegateEntries { + pub statements: Vec, pub entries: Punctuated, } impl Parse for DelegateEntries { fn parse(input: ParseStream) -> syn::Result { + let mut statements = Vec::new(); + + let fork = input.fork(); + + while let Ok(statement) = fork.parse() { + input.advance_to(&fork); + statements.push(statement); + } + let entries = Punctuated::parse_terminated(input)?; - Ok(Self { entries }) + + Ok(Self { + statements, + entries, + }) } } @@ -27,19 +43,24 @@ impl DelegateEntries { ) -> syn::Result> { let mut item_impls = Vec::new(); + let mut evaluated_entries = Vec::new(); + + for statement in &self.statements { + evaluated_entries.extend(statement.eval(&table_type)?); + } + for entry in &self.entries { - let evaluated_entries = entry.eval(&table_type)?; + evaluated_entries.extend(entry.eval(&table_type)?); + } - for evaluated_entry in evaluated_entries { - let delegate_component_impl = - evaluated_entry.build_delegate_component_impl(outer_generics)?; + for evaluated_entry in evaluated_entries { + let delegate_component_impl = + evaluated_entry.build_delegate_component_impl(outer_generics)?; - let is_provider_impl = - evaluated_entry.build_is_provider_for_impl(outer_generics)?; + let is_provider_impl = evaluated_entry.build_is_provider_for_impl(outer_generics)?; - item_impls.push(delegate_component_impl); - item_impls.push(is_provider_impl); - } + item_impls.push(delegate_component_impl); + item_impls.push(is_provider_impl); } Ok(item_impls) diff --git a/crates/cgp-macro-core/src/types/delegate_component/entry/combined.rs b/crates/cgp-macro-core/src/types/delegate_component/entry/mapping.rs similarity index 100% rename from crates/cgp-macro-core/src/types/delegate_component/entry/combined.rs rename to crates/cgp-macro-core/src/types/delegate_component/entry/mapping.rs diff --git a/crates/cgp-macro-core/src/types/delegate_component/entry/mod.rs b/crates/cgp-macro-core/src/types/delegate_component/entry/mod.rs index a57949cc..82a65262 100644 --- a/crates/cgp-macro-core/src/types/delegate_component/entry/mod.rs +++ b/crates/cgp-macro-core/src/types/delegate_component/entry/mod.rs @@ -1,15 +1,17 @@ -mod combined; mod direct; mod eval; +mod mapping; mod mode; mod namespace; mod normal; mod open; +mod statement; -pub use combined::*; pub use direct::*; pub use eval::*; +pub use mapping::*; pub use mode::*; pub use namespace::*; pub use normal::*; pub use open::*; +pub use statement::*; diff --git a/crates/cgp-macro-core/src/types/delegate_component/entry/namespace.rs b/crates/cgp-macro-core/src/types/delegate_component/entry/namespace.rs index 568d67dc..0138676e 100644 --- a/crates/cgp-macro-core/src/types/delegate_component/entry/namespace.rs +++ b/crates/cgp-macro-core/src/types/delegate_component/entry/namespace.rs @@ -1,4 +1,5 @@ use syn::parse::{Parse, ParseStream}; +use syn::token::Semi; use syn::{Ident, Type, parse_quote}; use crate::types::delegate_component::{EvalDelegateEntry, EvaluatedDelegateEntry}; @@ -9,14 +10,20 @@ use crate::types::keywords::Namespace; pub struct NamespaceDelegateEntry { pub namespace: Keyword, pub ident: Ident, + pub semi: Semi, } impl Parse for NamespaceDelegateEntry { fn parse(input: ParseStream) -> syn::Result { let namespace = input.parse()?; let ident = input.parse()?; + let semi = input.parse()?; - Ok(Self { namespace, ident }) + Ok(Self { + namespace, + ident, + semi, + }) } } diff --git a/crates/cgp-macro-core/src/types/delegate_component/entry/open.rs b/crates/cgp-macro-core/src/types/delegate_component/entry/open.rs index ebdbd1aa..2c1ea680 100644 --- a/crates/cgp-macro-core/src/types/delegate_component/entry/open.rs +++ b/crates/cgp-macro-core/src/types/delegate_component/entry/open.rs @@ -1,6 +1,6 @@ use syn::parse::{Parse, ParseStream}; use syn::punctuated::Punctuated; -use syn::token::Comma; +use syn::token::{Comma, Semi}; use syn::{Type, braced, parse_quote}; use crate::exports::{Nil, PathCons, RedirectLookup}; @@ -12,6 +12,7 @@ use crate::types::keywords::Open; pub struct OpenDelegateEntry { pub open: Keyword, pub components: Punctuated, + pub semi: Semi, } impl Parse for OpenDelegateEntry { @@ -25,7 +26,13 @@ impl Parse for OpenDelegateEntry { Punctuated::parse_terminated(&body)? }; - Ok(Self { open, components }) + let semi = input.parse()?; + + Ok(Self { + open, + components, + semi, + }) } } diff --git a/crates/cgp-macro-core/src/types/delegate_component/entry/statement.rs b/crates/cgp-macro-core/src/types/delegate_component/entry/statement.rs new file mode 100644 index 00000000..ccbad15a --- /dev/null +++ b/crates/cgp-macro-core/src/types/delegate_component/entry/statement.rs @@ -0,0 +1,37 @@ +use syn::parse::{Parse, ParseStream}; +use syn::{Error, Type}; + +use crate::traits::PeekKeyword; +use crate::types::delegate_component::{ + EvalDelegateEntry, EvaluatedDelegateEntry, NamespaceDelegateEntry, OpenDelegateEntry, +}; +use crate::types::keywords::{Namespace, Open}; + +#[derive(Debug, Clone)] +pub enum DelegateStatement { + Namespace(NamespaceDelegateEntry), + Open(OpenDelegateEntry), +} + +impl Parse for DelegateStatement { + fn parse(input: ParseStream) -> syn::Result { + if input.peek_keyword::() { + let namespace_entry = input.parse()?; + Ok(Self::Namespace(namespace_entry)) + } else if input.peek_keyword::() { + let open_entry = input.parse()?; + Ok(Self::Open(open_entry)) + } else { + Err(Error::new(input.span(), "invalid delegate statement")) + } + } +} + +impl EvalDelegateEntry for DelegateStatement { + fn eval(&self, table_type: &Type) -> syn::Result> { + match self { + Self::Namespace(entry) => entry.eval(table_type), + Self::Open(entry) => entry.eval(table_type), + } + } +} diff --git a/crates/cgp-tests/tests/namespace_tests/multi_param.rs b/crates/cgp-tests/tests/namespace_tests/multi_param.rs index f6290bc8..eaaa7f37 100644 --- a/crates/cgp-tests/tests/namespace_tests/multi_param.rs +++ b/crates/cgp-tests/tests/namespace_tests/multi_param.rs @@ -15,7 +15,7 @@ pub struct AppA; delegate_components! { AppA { - open {FooProviderComponent}, + open {FooProviderComponent}; @FooProviderComponent.String.u32: DummyFoo, @@ -39,7 +39,7 @@ pub struct AppB; delegate_components! { AppB { - namespace default, + namespace default; @app.FooProviderComponent.String.u64: DummyFoo, diff --git a/crates/cgp-tests/tests/namespace_tests/namespace.rs b/crates/cgp-tests/tests/namespace_tests/namespace.rs index ea272b36..a16834a5 100644 --- a/crates/cgp-tests/tests/namespace_tests/namespace.rs +++ b/crates/cgp-tests/tests/namespace_tests/namespace.rs @@ -14,7 +14,7 @@ pub struct App; delegate_components! { App { - namespace default, + namespace default; @cgp.core.error.ErrorTypeProviderComponent: UseType, diff --git a/crates/cgp-tests/tests/namespace_tests/namespace_macro/basic.rs b/crates/cgp-tests/tests/namespace_tests/namespace_macro/basic.rs index 3e06ef62..4e4d23b0 100644 --- a/crates/cgp-tests/tests/namespace_tests/namespace_macro/basic.rs +++ b/crates/cgp-tests/tests/namespace_tests/namespace_macro/basic.rs @@ -35,7 +35,7 @@ pub struct App; delegate_components! { App { - namespace MyNamespace, + namespace MyNamespace; @MyFooComponent: DummyFoo, diff --git a/crates/cgp-tests/tests/namespace_tests/namespace_macro/default_generics.rs b/crates/cgp-tests/tests/namespace_tests/namespace_macro/default_generics.rs index ba794217..b23f5c68 100644 --- a/crates/cgp-tests/tests/namespace_tests/namespace_macro/default_generics.rs +++ b/crates/cgp-tests/tests/namespace_tests/namespace_macro/default_generics.rs @@ -6,7 +6,7 @@ pub struct App; delegate_components! { App { - namespace default, + namespace default; @test.ShowImplComponent.u64: ShowWithDisplay, diff --git a/crates/cgp-tests/tests/namespace_tests/namespace_macro/extended_namespace.rs b/crates/cgp-tests/tests/namespace_tests/namespace_macro/extended_namespace.rs index 64fe931c..64d08afb 100644 --- a/crates/cgp-tests/tests/namespace_tests/namespace_macro/extended_namespace.rs +++ b/crates/cgp-tests/tests/namespace_tests/namespace_macro/extended_namespace.rs @@ -8,7 +8,7 @@ pub struct App; delegate_components! { App { - namespace ExtendedNamespace, + namespace ExtendedNamespace; @app.ErrorTypeProviderComponent: UseType, diff --git a/crates/cgp-tests/tests/namespace_tests/namespace_macro/multi_namespace.rs b/crates/cgp-tests/tests/namespace_tests/namespace_macro/multi_namespace.rs index 4fef0421..199bfa0a 100644 --- a/crates/cgp-tests/tests/namespace_tests/namespace_macro/multi_namespace.rs +++ b/crates/cgp-tests/tests/namespace_tests/namespace_macro/multi_namespace.rs @@ -46,7 +46,7 @@ pub struct App; delegate_components! { App { - namespace MyNamespace, + namespace MyNamespace; @MyApp.MyFooComponent: DummyFoo, @@ -66,7 +66,7 @@ pub struct OtherApp; delegate_components! { OtherApp { - namespace OtherNamespace, + namespace OtherNamespace; @my_app.MyFooComponent: DummyFoo, diff --git a/crates/cgp-tests/tests/namespace_tests/namespace_macro/symbol_path.rs b/crates/cgp-tests/tests/namespace_tests/namespace_macro/symbol_path.rs index 7c88819f..b840bea4 100644 --- a/crates/cgp-tests/tests/namespace_tests/namespace_macro/symbol_path.rs +++ b/crates/cgp-tests/tests/namespace_tests/namespace_macro/symbol_path.rs @@ -36,7 +36,7 @@ pub struct App; delegate_components! { App { - namespace MyNamespace, + namespace MyNamespace; @my_app.MyFooComponent: DummyFoo, diff --git a/crates/cgp-tests/tests/namespace_tests/namespace_macro/type_path.rs b/crates/cgp-tests/tests/namespace_tests/namespace_macro/type_path.rs index 748e0630..bdf477e5 100644 --- a/crates/cgp-tests/tests/namespace_tests/namespace_macro/type_path.rs +++ b/crates/cgp-tests/tests/namespace_tests/namespace_macro/type_path.rs @@ -38,7 +38,7 @@ pub struct App; delegate_components! { App { - namespace MyNamespace, + namespace MyNamespace; @MyApp.MyFooComponent: DummyFoo, diff --git a/crates/cgp-tests/tests/namespace_tests/open.rs b/crates/cgp-tests/tests/namespace_tests/open.rs index 68afae36..42367b9d 100644 --- a/crates/cgp-tests/tests/namespace_tests/open.rs +++ b/crates/cgp-tests/tests/namespace_tests/open.rs @@ -24,7 +24,7 @@ impl BarProvider { delegate_components! { App { - open {FooProviderComponent, BarProviderComponent}, + open {FooProviderComponent, BarProviderComponent}; @FooProviderComponent.String: DummyFoo, diff --git a/crates/cgp-tests/tests/namespace_tests/redirect.rs b/crates/cgp-tests/tests/namespace_tests/redirect.rs index 9d3b2bc0..d86dbf45 100644 --- a/crates/cgp-tests/tests/namespace_tests/redirect.rs +++ b/crates/cgp-tests/tests/namespace_tests/redirect.rs @@ -19,7 +19,7 @@ pub struct App; delegate_components! { App { - namespace default, + namespace default; // @bar: TestProvider, From 1f1ae5ddaa86d35e91316275e8034418e7c7591c Mon Sep 17 00:00:00 2001 From: Soares Chen Date: Sun, 24 May 2026 21:00:35 +0200 Subject: [PATCH 58/81] Rename DelegateEntry to DelegateMapping --- .../src/types/delegate_component/entries.rs | 4 +- .../types/delegate_component/entry/mapping.rs | 47 +++++-------------- 2 files changed, 15 insertions(+), 36 deletions(-) diff --git a/crates/cgp-macro-core/src/types/delegate_component/entries.rs b/crates/cgp-macro-core/src/types/delegate_component/entries.rs index 7f7c34ab..4acda051 100644 --- a/crates/cgp-macro-core/src/types/delegate_component/entries.rs +++ b/crates/cgp-macro-core/src/types/delegate_component/entries.rs @@ -5,14 +5,14 @@ use syn::token::Comma; use syn::{Generics, ItemImpl, Type}; use crate::types::delegate_component::{ - DelegateEntry, DelegateStatement, EvalDelegateEntry, ExtractInnerDelegateTables, + DelegateMapping, DelegateStatement, EvalDelegateEntry, ExtractInnerDelegateTables, InnerDelegateTable, }; #[derive(Debug, Clone)] pub struct DelegateEntries { pub statements: Vec, - pub entries: Punctuated, + pub entries: Punctuated, } impl Parse for DelegateEntries { diff --git a/crates/cgp-macro-core/src/types/delegate_component/entry/mapping.rs b/crates/cgp-macro-core/src/types/delegate_component/entry/mapping.rs index 7d6f1a40..4ac51b2a 100644 --- a/crates/cgp-macro-core/src/types/delegate_component/entry/mapping.rs +++ b/crates/cgp-macro-core/src/types/delegate_component/entry/mapping.rs @@ -1,67 +1,46 @@ use syn::Type; use syn::parse::{Parse, ParseStream}; -use crate::traits::PeekKeyword; use crate::types::delegate_component::{ DelegateMode, DirectDelegateEntry, EvalDelegateEntry, EvaluatedDelegateEntry, - ExtractInnerDelegateTables, InnerDelegateTable, NamespaceDelegateEntry, NormalDelegateEntry, - OpenDelegateEntry, + ExtractInnerDelegateTables, InnerDelegateTable, NormalDelegateEntry, }; -use crate::types::keywords::{Namespace, Open}; #[derive(Debug, Clone)] -pub enum DelegateEntry { +pub enum DelegateMapping { Normal(NormalDelegateEntry), Direct(DirectDelegateEntry), - Namespace(NamespaceDelegateEntry), - Open(OpenDelegateEntry), } -impl Parse for DelegateEntry { +impl Parse for DelegateMapping { fn parse(input: ParseStream) -> syn::Result { - if input.peek_keyword::() { - let namespace_entry = input.parse()?; - Ok(Self::Namespace(namespace_entry)) - } else if input.peek_keyword::() { - let open_entry = input.parse()?; - Ok(Self::Open(open_entry)) - } else { - let key = input.parse()?; - let mode: DelegateMode = input.parse()?; - let value = input.parse()?; + let key = input.parse()?; + let mode: DelegateMode = input.parse()?; + let value = input.parse()?; - let entry = match mode { - DelegateMode::Normal(colon) => { - Self::Normal(NormalDelegateEntry { key, colon, value }) - } - DelegateMode::Direct(arrow) => { - Self::Direct(DirectDelegateEntry { key, arrow, value }) - } - }; + let entry = match mode { + DelegateMode::Normal(colon) => Self::Normal(NormalDelegateEntry { key, colon, value }), + DelegateMode::Direct(arrow) => Self::Direct(DirectDelegateEntry { key, arrow, value }), + }; - Ok(entry) - } + Ok(entry) } } -impl EvalDelegateEntry for DelegateEntry { +impl EvalDelegateEntry for DelegateMapping { fn eval(&self, table_type: &Type) -> syn::Result> { match self { Self::Normal(entry) => entry.eval(table_type), Self::Direct(entry) => entry.eval(table_type), - Self::Namespace(entry) => entry.eval(table_type), - Self::Open(entry) => entry.eval(table_type), } } } -impl ExtractInnerDelegateTables for DelegateEntry { +impl ExtractInnerDelegateTables for DelegateMapping { fn extract_inner_tables(&self) -> Vec { match self { Self::Normal(entry) => entry.extract_inner_tables(), Self::Direct(entry) => entry.extract_inner_tables(), - Self::Namespace(_) => Vec::new(), - Self::Open(_) => Vec::new(), } } } From 381ed203485b675080e7472950ae62b3f8df306a Mon Sep 17 00:00:00 2001 From: Soares Chen Date: Mon, 25 May 2026 11:51:43 +0200 Subject: [PATCH 59/81] Reorganize statement modules --- .../src/types/delegate_component/entry/mod.rs | 6 ------ crates/cgp-macro-core/src/types/delegate_component/mod.rs | 2 ++ .../{entry/statement.rs => statement/combined.rs} | 0 .../src/types/delegate_component/statement/mod.rs | 7 +++++++ .../delegate_component/{entry => statement}/namespace.rs | 0 .../types/delegate_component/{entry => statement}/open.rs | 0 .../namespace_tests/namespace_macro/default_generics.rs | 7 +++++++ crates/cgp-tests/tests/namespace_tests/open.rs | 1 + 8 files changed, 17 insertions(+), 6 deletions(-) rename crates/cgp-macro-core/src/types/delegate_component/{entry/statement.rs => statement/combined.rs} (100%) create mode 100644 crates/cgp-macro-core/src/types/delegate_component/statement/mod.rs rename crates/cgp-macro-core/src/types/delegate_component/{entry => statement}/namespace.rs (100%) rename crates/cgp-macro-core/src/types/delegate_component/{entry => statement}/open.rs (100%) diff --git a/crates/cgp-macro-core/src/types/delegate_component/entry/mod.rs b/crates/cgp-macro-core/src/types/delegate_component/entry/mod.rs index 82a65262..317c98b1 100644 --- a/crates/cgp-macro-core/src/types/delegate_component/entry/mod.rs +++ b/crates/cgp-macro-core/src/types/delegate_component/entry/mod.rs @@ -2,16 +2,10 @@ mod direct; mod eval; mod mapping; mod mode; -mod namespace; mod normal; -mod open; -mod statement; pub use direct::*; pub use eval::*; pub use mapping::*; pub use mode::*; -pub use namespace::*; pub use normal::*; -pub use open::*; -pub use statement::*; diff --git a/crates/cgp-macro-core/src/types/delegate_component/mod.rs b/crates/cgp-macro-core/src/types/delegate_component/mod.rs index 315e0b66..509f39fb 100644 --- a/crates/cgp-macro-core/src/types/delegate_component/mod.rs +++ b/crates/cgp-macro-core/src/types/delegate_component/mod.rs @@ -1,11 +1,13 @@ mod entries; mod entry; mod key; +mod statement; mod table; mod value; pub use entries::*; pub use entry::*; pub use key::*; +pub use statement::*; pub use table::*; pub use value::*; diff --git a/crates/cgp-macro-core/src/types/delegate_component/entry/statement.rs b/crates/cgp-macro-core/src/types/delegate_component/statement/combined.rs similarity index 100% rename from crates/cgp-macro-core/src/types/delegate_component/entry/statement.rs rename to crates/cgp-macro-core/src/types/delegate_component/statement/combined.rs diff --git a/crates/cgp-macro-core/src/types/delegate_component/statement/mod.rs b/crates/cgp-macro-core/src/types/delegate_component/statement/mod.rs new file mode 100644 index 00000000..20b0a520 --- /dev/null +++ b/crates/cgp-macro-core/src/types/delegate_component/statement/mod.rs @@ -0,0 +1,7 @@ +mod combined; +mod namespace; +mod open; + +pub use combined::*; +pub use namespace::*; +pub use open::*; diff --git a/crates/cgp-macro-core/src/types/delegate_component/entry/namespace.rs b/crates/cgp-macro-core/src/types/delegate_component/statement/namespace.rs similarity index 100% rename from crates/cgp-macro-core/src/types/delegate_component/entry/namespace.rs rename to crates/cgp-macro-core/src/types/delegate_component/statement/namespace.rs diff --git a/crates/cgp-macro-core/src/types/delegate_component/entry/open.rs b/crates/cgp-macro-core/src/types/delegate_component/statement/open.rs similarity index 100% rename from crates/cgp-macro-core/src/types/delegate_component/entry/open.rs rename to crates/cgp-macro-core/src/types/delegate_component/statement/open.rs diff --git a/crates/cgp-tests/tests/namespace_tests/namespace_macro/default_generics.rs b/crates/cgp-tests/tests/namespace_tests/namespace_macro/default_generics.rs index b23f5c68..c9ba4b0c 100644 --- a/crates/cgp-tests/tests/namespace_tests/namespace_macro/default_generics.rs +++ b/crates/cgp-tests/tests/namespace_tests/namespace_macro/default_generics.rs @@ -6,11 +6,18 @@ pub struct App; delegate_components! { App { + // use DefaultNamespace; + // for in DefaultNamespace { + // Component: Provider, + // } namespace default; @test.ShowImplComponent.u64: ShowWithDisplay, + // for in DefaultNamespace1 { + // @test.ShowImplComponent.T: Provider, + // } // namespace DefaultNamespace1 => @test.ShowImplComponent; } } diff --git a/crates/cgp-tests/tests/namespace_tests/open.rs b/crates/cgp-tests/tests/namespace_tests/open.rs index 42367b9d..52fe6818 100644 --- a/crates/cgp-tests/tests/namespace_tests/open.rs +++ b/crates/cgp-tests/tests/namespace_tests/open.rs @@ -24,6 +24,7 @@ impl BarProvider { delegate_components! { App { + // FooProviderComponent => @FooProviderComponent, open {FooProviderComponent, BarProviderComponent}; @FooProviderComponent.String: From 905dbe0cec6dccb8008a8b9bb260a3ceea79fd4a Mon Sep 17 00:00:00 2001 From: Soares Chen Date: Mon, 25 May 2026 11:52:39 +0200 Subject: [PATCH 60/81] Reorganize mapping constructs --- .../{entry/mapping.rs => mapping/combined.rs} | 0 .../src/types/delegate_component/{entry => mapping}/direct.rs | 0 .../src/types/delegate_component/{entry => mapping}/eval.rs | 0 .../src/types/delegate_component/{entry => mapping}/mod.rs | 4 ++-- .../src/types/delegate_component/{entry => mapping}/mode.rs | 0 .../src/types/delegate_component/{entry => mapping}/normal.rs | 0 crates/cgp-macro-core/src/types/delegate_component/mod.rs | 4 ++-- 7 files changed, 4 insertions(+), 4 deletions(-) rename crates/cgp-macro-core/src/types/delegate_component/{entry/mapping.rs => mapping/combined.rs} (100%) rename crates/cgp-macro-core/src/types/delegate_component/{entry => mapping}/direct.rs (100%) rename crates/cgp-macro-core/src/types/delegate_component/{entry => mapping}/eval.rs (100%) rename crates/cgp-macro-core/src/types/delegate_component/{entry => mapping}/mod.rs (76%) rename crates/cgp-macro-core/src/types/delegate_component/{entry => mapping}/mode.rs (100%) rename crates/cgp-macro-core/src/types/delegate_component/{entry => mapping}/normal.rs (100%) diff --git a/crates/cgp-macro-core/src/types/delegate_component/entry/mapping.rs b/crates/cgp-macro-core/src/types/delegate_component/mapping/combined.rs similarity index 100% rename from crates/cgp-macro-core/src/types/delegate_component/entry/mapping.rs rename to crates/cgp-macro-core/src/types/delegate_component/mapping/combined.rs diff --git a/crates/cgp-macro-core/src/types/delegate_component/entry/direct.rs b/crates/cgp-macro-core/src/types/delegate_component/mapping/direct.rs similarity index 100% rename from crates/cgp-macro-core/src/types/delegate_component/entry/direct.rs rename to crates/cgp-macro-core/src/types/delegate_component/mapping/direct.rs diff --git a/crates/cgp-macro-core/src/types/delegate_component/entry/eval.rs b/crates/cgp-macro-core/src/types/delegate_component/mapping/eval.rs similarity index 100% rename from crates/cgp-macro-core/src/types/delegate_component/entry/eval.rs rename to crates/cgp-macro-core/src/types/delegate_component/mapping/eval.rs diff --git a/crates/cgp-macro-core/src/types/delegate_component/entry/mod.rs b/crates/cgp-macro-core/src/types/delegate_component/mapping/mod.rs similarity index 76% rename from crates/cgp-macro-core/src/types/delegate_component/entry/mod.rs rename to crates/cgp-macro-core/src/types/delegate_component/mapping/mod.rs index 317c98b1..ae0c2709 100644 --- a/crates/cgp-macro-core/src/types/delegate_component/entry/mod.rs +++ b/crates/cgp-macro-core/src/types/delegate_component/mapping/mod.rs @@ -1,11 +1,11 @@ +mod combined; mod direct; mod eval; -mod mapping; mod mode; mod normal; +pub use combined::*; pub use direct::*; pub use eval::*; -pub use mapping::*; pub use mode::*; pub use normal::*; diff --git a/crates/cgp-macro-core/src/types/delegate_component/entry/mode.rs b/crates/cgp-macro-core/src/types/delegate_component/mapping/mode.rs similarity index 100% rename from crates/cgp-macro-core/src/types/delegate_component/entry/mode.rs rename to crates/cgp-macro-core/src/types/delegate_component/mapping/mode.rs diff --git a/crates/cgp-macro-core/src/types/delegate_component/entry/normal.rs b/crates/cgp-macro-core/src/types/delegate_component/mapping/normal.rs similarity index 100% rename from crates/cgp-macro-core/src/types/delegate_component/entry/normal.rs rename to crates/cgp-macro-core/src/types/delegate_component/mapping/normal.rs diff --git a/crates/cgp-macro-core/src/types/delegate_component/mod.rs b/crates/cgp-macro-core/src/types/delegate_component/mod.rs index 509f39fb..30440c2c 100644 --- a/crates/cgp-macro-core/src/types/delegate_component/mod.rs +++ b/crates/cgp-macro-core/src/types/delegate_component/mod.rs @@ -1,13 +1,13 @@ mod entries; -mod entry; mod key; +mod mapping; mod statement; mod table; mod value; pub use entries::*; -pub use entry::*; pub use key::*; +pub use mapping::*; pub use statement::*; pub use table::*; pub use value::*; From 23c45465882dca00d26a7a606f3a1d8d16ae5862 Mon Sep 17 00:00:00 2001 From: Soares Chen Date: Mon, 25 May 2026 11:54:51 +0200 Subject: [PATCH 61/81] Rename mapping and statement constructs --- .../types/delegate_component/mapping/combined.rs | 16 ++++++++++------ .../types/delegate_component/mapping/direct.rs | 6 +++--- .../types/delegate_component/mapping/normal.rs | 6 +++--- .../delegate_component/statement/combined.rs | 6 +++--- .../delegate_component/statement/namespace.rs | 6 +++--- .../types/delegate_component/statement/open.rs | 6 +++--- 6 files changed, 25 insertions(+), 21 deletions(-) diff --git a/crates/cgp-macro-core/src/types/delegate_component/mapping/combined.rs b/crates/cgp-macro-core/src/types/delegate_component/mapping/combined.rs index 4ac51b2a..0f53d885 100644 --- a/crates/cgp-macro-core/src/types/delegate_component/mapping/combined.rs +++ b/crates/cgp-macro-core/src/types/delegate_component/mapping/combined.rs @@ -2,14 +2,14 @@ use syn::Type; use syn::parse::{Parse, ParseStream}; use crate::types::delegate_component::{ - DelegateMode, DirectDelegateEntry, EvalDelegateEntry, EvaluatedDelegateEntry, - ExtractInnerDelegateTables, InnerDelegateTable, NormalDelegateEntry, + DelegateMode, DirectDelegateMapping, EvalDelegateEntry, EvaluatedDelegateEntry, + ExtractInnerDelegateTables, InnerDelegateTable, NormalDelegateMapping, }; #[derive(Debug, Clone)] pub enum DelegateMapping { - Normal(NormalDelegateEntry), - Direct(DirectDelegateEntry), + Normal(NormalDelegateMapping), + Direct(DirectDelegateMapping), } impl Parse for DelegateMapping { @@ -19,8 +19,12 @@ impl Parse for DelegateMapping { let value = input.parse()?; let entry = match mode { - DelegateMode::Normal(colon) => Self::Normal(NormalDelegateEntry { key, colon, value }), - DelegateMode::Direct(arrow) => Self::Direct(DirectDelegateEntry { key, arrow, value }), + DelegateMode::Normal(colon) => { + Self::Normal(NormalDelegateMapping { key, colon, value }) + } + DelegateMode::Direct(arrow) => { + Self::Direct(DirectDelegateMapping { key, arrow, value }) + } }; Ok(entry) diff --git a/crates/cgp-macro-core/src/types/delegate_component/mapping/direct.rs b/crates/cgp-macro-core/src/types/delegate_component/mapping/direct.rs index b2aa7c6c..9ee19ce3 100644 --- a/crates/cgp-macro-core/src/types/delegate_component/mapping/direct.rs +++ b/crates/cgp-macro-core/src/types/delegate_component/mapping/direct.rs @@ -8,13 +8,13 @@ use crate::types::delegate_component::{ }; #[derive(Debug, Clone)] -pub struct DirectDelegateEntry { +pub struct DirectDelegateMapping { pub key: DelegateKey, pub arrow: RArrow, pub value: DelegateValue, } -impl EvalDelegateEntry for DirectDelegateEntry { +impl EvalDelegateEntry for DirectDelegateMapping { fn eval(&self, table_type: &Type) -> syn::Result> { let keys = self.key.eval()?; let value_type = self.value.eval()?; @@ -51,7 +51,7 @@ impl EvalDelegateEntry for DirectDelegateEntry { } } -impl ExtractInnerDelegateTables for DirectDelegateEntry { +impl ExtractInnerDelegateTables for DirectDelegateMapping { fn extract_inner_tables(&self) -> Vec { self.value.extract_inner_tables() } diff --git a/crates/cgp-macro-core/src/types/delegate_component/mapping/normal.rs b/crates/cgp-macro-core/src/types/delegate_component/mapping/normal.rs index 7636f5b4..72aae169 100644 --- a/crates/cgp-macro-core/src/types/delegate_component/mapping/normal.rs +++ b/crates/cgp-macro-core/src/types/delegate_component/mapping/normal.rs @@ -7,13 +7,13 @@ use crate::types::delegate_component::{ }; #[derive(Debug, Clone)] -pub struct NormalDelegateEntry { +pub struct NormalDelegateMapping { pub key: DelegateKey, pub colon: Colon, pub value: DelegateValue, } -impl EvalDelegateEntry for NormalDelegateEntry { +impl EvalDelegateEntry for NormalDelegateMapping { fn eval(&self, table_type: &Type) -> syn::Result> { let keys = self.key.eval()?; let value_type = self.value.eval()?; @@ -32,7 +32,7 @@ impl EvalDelegateEntry for NormalDelegateEntry { } } -impl ExtractInnerDelegateTables for NormalDelegateEntry { +impl ExtractInnerDelegateTables for NormalDelegateMapping { fn extract_inner_tables(&self) -> Vec { self.value.extract_inner_tables() } diff --git a/crates/cgp-macro-core/src/types/delegate_component/statement/combined.rs b/crates/cgp-macro-core/src/types/delegate_component/statement/combined.rs index ccbad15a..5a050a4c 100644 --- a/crates/cgp-macro-core/src/types/delegate_component/statement/combined.rs +++ b/crates/cgp-macro-core/src/types/delegate_component/statement/combined.rs @@ -3,14 +3,14 @@ use syn::{Error, Type}; use crate::traits::PeekKeyword; use crate::types::delegate_component::{ - EvalDelegateEntry, EvaluatedDelegateEntry, NamespaceDelegateEntry, OpenDelegateEntry, + EvalDelegateEntry, EvaluatedDelegateEntry, NamespaceDelegateStatement, OpenDelegateStatement, }; use crate::types::keywords::{Namespace, Open}; #[derive(Debug, Clone)] pub enum DelegateStatement { - Namespace(NamespaceDelegateEntry), - Open(OpenDelegateEntry), + Namespace(NamespaceDelegateStatement), + Open(OpenDelegateStatement), } impl Parse for DelegateStatement { diff --git a/crates/cgp-macro-core/src/types/delegate_component/statement/namespace.rs b/crates/cgp-macro-core/src/types/delegate_component/statement/namespace.rs index 0138676e..daad0198 100644 --- a/crates/cgp-macro-core/src/types/delegate_component/statement/namespace.rs +++ b/crates/cgp-macro-core/src/types/delegate_component/statement/namespace.rs @@ -7,13 +7,13 @@ use crate::types::keyword::Keyword; use crate::types::keywords::Namespace; #[derive(Debug, Clone)] -pub struct NamespaceDelegateEntry { +pub struct NamespaceDelegateStatement { pub namespace: Keyword, pub ident: Ident, pub semi: Semi, } -impl Parse for NamespaceDelegateEntry { +impl Parse for NamespaceDelegateStatement { fn parse(input: ParseStream) -> syn::Result { let namespace = input.parse()?; let ident = input.parse()?; @@ -27,7 +27,7 @@ impl Parse for NamespaceDelegateEntry { } } -impl EvalDelegateEntry for NamespaceDelegateEntry { +impl EvalDelegateEntry for NamespaceDelegateStatement { fn eval(&self, table_type: &Type) -> syn::Result> { let namespace_ident = if &self.ident == "default" { Ident::new("DefaultNamespace", self.ident.span()) diff --git a/crates/cgp-macro-core/src/types/delegate_component/statement/open.rs b/crates/cgp-macro-core/src/types/delegate_component/statement/open.rs index 2c1ea680..c00555b7 100644 --- a/crates/cgp-macro-core/src/types/delegate_component/statement/open.rs +++ b/crates/cgp-macro-core/src/types/delegate_component/statement/open.rs @@ -9,13 +9,13 @@ use crate::types::keyword::Keyword; use crate::types::keywords::Open; #[derive(Debug, Clone)] -pub struct OpenDelegateEntry { +pub struct OpenDelegateStatement { pub open: Keyword, pub components: Punctuated, pub semi: Semi, } -impl Parse for OpenDelegateEntry { +impl Parse for OpenDelegateStatement { fn parse(input: ParseStream) -> syn::Result { let open = input.parse()?; @@ -36,7 +36,7 @@ impl Parse for OpenDelegateEntry { } } -impl EvalDelegateEntry for OpenDelegateEntry { +impl EvalDelegateEntry for OpenDelegateStatement { fn eval(&self, table_type: &Type) -> syn::Result> { let mut entries = Vec::new(); From 1268856be97570166d7ba9556265e2867adda40e Mon Sep 17 00:00:00 2001 From: Soares Chen Date: Mon, 25 May 2026 13:24:08 +0200 Subject: [PATCH 62/81] Scaffold parsing for for statement --- .../src/types/delegate_component/entries.rs | 7 +-- .../delegate_component/statement/combined.rs | 15 ++++- .../delegate_component/statement/for_loop.rs | 61 +++++++++++++++++++ .../types/delegate_component/statement/mod.rs | 2 + .../namespace_macro/default_generics.rs | 7 ++- 5 files changed, 83 insertions(+), 9 deletions(-) create mode 100644 crates/cgp-macro-core/src/types/delegate_component/statement/for_loop.rs diff --git a/crates/cgp-macro-core/src/types/delegate_component/entries.rs b/crates/cgp-macro-core/src/types/delegate_component/entries.rs index 4acda051..e4bed06b 100644 --- a/crates/cgp-macro-core/src/types/delegate_component/entries.rs +++ b/crates/cgp-macro-core/src/types/delegate_component/entries.rs @@ -1,4 +1,3 @@ -use syn::parse::discouraged::Speculative; use syn::parse::{Parse, ParseStream}; use syn::punctuated::Punctuated; use syn::token::Comma; @@ -19,10 +18,8 @@ impl Parse for DelegateEntries { fn parse(input: ParseStream) -> syn::Result { let mut statements = Vec::new(); - let fork = input.fork(); - - while let Ok(statement) = fork.parse() { - input.advance_to(&fork); + while DelegateStatement::peek_statement(input) { + let statement = input.parse()?; statements.push(statement); } diff --git a/crates/cgp-macro-core/src/types/delegate_component/statement/combined.rs b/crates/cgp-macro-core/src/types/delegate_component/statement/combined.rs index 5a050a4c..dd5f53d6 100644 --- a/crates/cgp-macro-core/src/types/delegate_component/statement/combined.rs +++ b/crates/cgp-macro-core/src/types/delegate_component/statement/combined.rs @@ -1,9 +1,11 @@ use syn::parse::{Parse, ParseStream}; +use syn::token::For; use syn::{Error, Type}; use crate::traits::PeekKeyword; use crate::types::delegate_component::{ - EvalDelegateEntry, EvaluatedDelegateEntry, NamespaceDelegateStatement, OpenDelegateStatement, + EvalDelegateEntry, EvaluatedDelegateEntry, ForDelegateStatement, NamespaceDelegateStatement, + OpenDelegateStatement, }; use crate::types::keywords::{Namespace, Open}; @@ -11,6 +13,13 @@ use crate::types::keywords::{Namespace, Open}; pub enum DelegateStatement { Namespace(NamespaceDelegateStatement), Open(OpenDelegateStatement), + For(ForDelegateStatement), +} + +impl DelegateStatement { + pub fn peek_statement(input: ParseStream) -> bool { + input.peek_keyword::() || input.peek_keyword::() || input.peek(For) + } } impl Parse for DelegateStatement { @@ -21,6 +30,9 @@ impl Parse for DelegateStatement { } else if input.peek_keyword::() { let open_entry = input.parse()?; Ok(Self::Open(open_entry)) + } else if input.peek(For) { + let for_entry = input.parse()?; + Ok(Self::For(for_entry)) } else { Err(Error::new(input.span(), "invalid delegate statement")) } @@ -32,6 +44,7 @@ impl EvalDelegateEntry for DelegateStatement { match self { Self::Namespace(entry) => entry.eval(table_type), Self::Open(entry) => entry.eval(table_type), + Self::For(entry) => entry.eval(table_type), } } } diff --git a/crates/cgp-macro-core/src/types/delegate_component/statement/for_loop.rs b/crates/cgp-macro-core/src/types/delegate_component/statement/for_loop.rs new file mode 100644 index 00000000..1386c1b0 --- /dev/null +++ b/crates/cgp-macro-core/src/types/delegate_component/statement/for_loop.rs @@ -0,0 +1,61 @@ +use syn::parse::{Parse, ParseStream}; +use syn::punctuated::Punctuated; +use syn::token::{Comma, For, Gt, In, Lt}; +use syn::{Ident, Type, WhereClause, braced}; + +use crate::types::delegate_component::{ + DelegateMapping, EvalDelegateEntry, EvaluatedDelegateEntry, +}; + +#[derive(Debug, Clone)] +pub struct ForDelegateStatement { + pub for_token: For, + pub lt: Lt, + pub key: Ident, + pub comma: Comma, + pub value: Ident, + pub gt: Gt, + pub in_token: In, + pub namespace: Type, + pub where_clause: Option, + pub mappings: Punctuated, +} + +impl Parse for ForDelegateStatement { + fn parse(input: ParseStream) -> syn::Result { + let for_token = input.parse()?; + let lt = input.parse()?; + let key = input.parse()?; + let comma = input.parse()?; + let value = input.parse()?; + let gt = input.parse()?; + let in_token = input.parse()?; + let namespace = input.parse()?; + let where_clause = input.parse()?; + + let mappings = { + let body; + braced!(body in input); + Punctuated::parse_terminated(&body)? + }; + + Ok(Self { + for_token, + lt, + key, + comma, + value, + gt, + in_token, + namespace, + where_clause, + mappings, + }) + } +} + +impl EvalDelegateEntry for ForDelegateStatement { + fn eval(&self, _table_type: &Type) -> syn::Result> { + Ok(Vec::new()) + } +} diff --git a/crates/cgp-macro-core/src/types/delegate_component/statement/mod.rs b/crates/cgp-macro-core/src/types/delegate_component/statement/mod.rs index 20b0a520..5f4d608f 100644 --- a/crates/cgp-macro-core/src/types/delegate_component/statement/mod.rs +++ b/crates/cgp-macro-core/src/types/delegate_component/statement/mod.rs @@ -1,7 +1,9 @@ mod combined; +mod for_loop; mod namespace; mod open; pub use combined::*; +pub use for_loop::*; pub use namespace::*; pub use open::*; diff --git a/crates/cgp-tests/tests/namespace_tests/namespace_macro/default_generics.rs b/crates/cgp-tests/tests/namespace_tests/namespace_macro/default_generics.rs index c9ba4b0c..ad5b625d 100644 --- a/crates/cgp-tests/tests/namespace_tests/namespace_macro/default_generics.rs +++ b/crates/cgp-tests/tests/namespace_tests/namespace_macro/default_generics.rs @@ -12,12 +12,13 @@ delegate_components! { // } namespace default; + for in DefaultNamespace1 { + @test.ShowImplComponent.T: Provider, + } + @test.ShowImplComponent.u64: ShowWithDisplay, - // for in DefaultNamespace1 { - // @test.ShowImplComponent.T: Provider, - // } // namespace DefaultNamespace1 => @test.ShowImplComponent; } } From fdcae742710269543dc79636c283b68df1707d56 Mon Sep 17 00:00:00 2001 From: Soares Chen Date: Mon, 25 May 2026 13:50:34 +0200 Subject: [PATCH 63/81] For statement is now working --- .../delegate_component/mapping/normal.rs | 11 +++ .../delegate_component/statement/for_loop.rs | 68 +++++++++++++++++-- crates/cgp-macro-core/src/types/ident_type.rs | 1 + .../namespace_macro/default_generics.rs | 16 ++--- 4 files changed, 82 insertions(+), 14 deletions(-) diff --git a/crates/cgp-macro-core/src/types/delegate_component/mapping/normal.rs b/crates/cgp-macro-core/src/types/delegate_component/mapping/normal.rs index 72aae169..ae928ba4 100644 --- a/crates/cgp-macro-core/src/types/delegate_component/mapping/normal.rs +++ b/crates/cgp-macro-core/src/types/delegate_component/mapping/normal.rs @@ -1,4 +1,5 @@ use syn::Type; +use syn::parse::{Parse, ParseStream}; use syn::token::Colon; use crate::types::delegate_component::{ @@ -13,6 +14,16 @@ pub struct NormalDelegateMapping { pub value: DelegateValue, } +impl Parse for NormalDelegateMapping { + fn parse(input: ParseStream) -> syn::Result { + let key = input.parse()?; + let colon = input.parse()?; + let value = input.parse()?; + + Ok(Self { key, colon, value }) + } +} + impl EvalDelegateEntry for NormalDelegateMapping { fn eval(&self, table_type: &Type) -> syn::Result> { let keys = self.key.eval()?; diff --git a/crates/cgp-macro-core/src/types/delegate_component/statement/for_loop.rs b/crates/cgp-macro-core/src/types/delegate_component/statement/for_loop.rs index 1386c1b0..07ebfd91 100644 --- a/crates/cgp-macro-core/src/types/delegate_component/statement/for_loop.rs +++ b/crates/cgp-macro-core/src/types/delegate_component/statement/for_loop.rs @@ -1,11 +1,13 @@ use syn::parse::{Parse, ParseStream}; use syn::punctuated::Punctuated; use syn::token::{Comma, For, Gt, In, Lt}; -use syn::{Ident, Type, WhereClause, braced}; +use syn::{Ident, Type, WhereClause, braced, parse_quote}; use crate::types::delegate_component::{ - DelegateMapping, EvalDelegateEntry, EvaluatedDelegateEntry, + EvalDelegateEntry, EvalDelegateKey, EvalDelegateValue, EvaluatedDelegateEntry, + NormalDelegateMapping, }; +use crate::types::ident_type::IdentType; #[derive(Debug, Clone)] pub struct ForDelegateStatement { @@ -16,9 +18,9 @@ pub struct ForDelegateStatement { pub value: Ident, pub gt: Gt, pub in_token: In, - pub namespace: Type, + pub namespace: IdentType, pub where_clause: Option, - pub mappings: Punctuated, + pub mappings: Punctuated, } impl Parse for ForDelegateStatement { @@ -55,7 +57,61 @@ impl Parse for ForDelegateStatement { } impl EvalDelegateEntry for ForDelegateStatement { - fn eval(&self, _table_type: &Type) -> syn::Result> { - Ok(Vec::new()) + fn eval(&self, table_type: &Type) -> syn::Result> { + let for_key = &self.key; + let for_value = &self.value; + let for_where = &self.where_clause; + + let namespace_ident = &self.namespace.ident; + let mut namespace_generics = self.namespace.generics.clone(); + namespace_generics + .generics + .params + .push(parse_quote!(#table_type)); + + let mut entries = Vec::new(); + + for mapping in &self.mappings { + let keys = mapping.key.eval()?; + let value_type = mapping.value.eval()?; + + for key in keys { + let key_type = key.key; + let value_type = value_type.clone(); + + let namespace_trait: Type = { + let mut namespace_generics = namespace_generics.clone(); + namespace_generics.generics.params.push(parse_quote! { + Provider = #value_type + }); + + parse_quote!( #namespace_ident #namespace_generics ) + }; + + let mut generics = key.generics; + generics.params.push(parse_quote!(#for_key)); + generics.params.push(parse_quote!(#for_value)); + + let where_clause = generics.make_where_clause(); + where_clause.predicates.push(parse_quote! { + #for_key: #namespace_trait + }); + + if let Some(for_where) = for_where { + where_clause.predicates.extend(for_where.predicates.clone()); + } + + let entry = EvaluatedDelegateEntry { + table_type: table_type.clone(), + generics, + key: key_type, + value: value_type, + }; + + entries.push(entry); + } + } + + Ok(entries) } } diff --git a/crates/cgp-macro-core/src/types/ident_type.rs b/crates/cgp-macro-core/src/types/ident_type.rs index 417836c8..2578807c 100644 --- a/crates/cgp-macro-core/src/types/ident_type.rs +++ b/crates/cgp-macro-core/src/types/ident_type.rs @@ -3,6 +3,7 @@ use syn::parse::{Parse, ParseStream}; use crate::types::generics::TypeGenerics; +#[derive(Debug, Clone)] pub struct IdentType { pub ident: Ident, pub generics: TypeGenerics, diff --git a/crates/cgp-tests/tests/namespace_tests/namespace_macro/default_generics.rs b/crates/cgp-tests/tests/namespace_tests/namespace_macro/default_generics.rs index ad5b625d..f40559e8 100644 --- a/crates/cgp-tests/tests/namespace_tests/namespace_macro/default_generics.rs +++ b/crates/cgp-tests/tests/namespace_tests/namespace_macro/default_generics.rs @@ -23,14 +23,14 @@ delegate_components! { } } -impl - DelegateComponent>>> - for App -where - T: DefaultNamespace1, -{ - type Delegate = T::Provider; -} +// impl +// DelegateComponent>>> +// for App +// where +// T: DefaultNamespace1, +// { +// type Delegate = T::Provider; +// } check_components! { App { From 4e8bc25dcc83a9a9273e89b61259a58a2ac79e36 Mon Sep 17 00:00:00 2001 From: Soares Chen Date: Mon, 25 May 2026 20:00:21 +0200 Subject: [PATCH 64/81] Implement EvaluatedForEntry --- .../delegate_component/statement/eval.rs | 62 ++++++++++++++++ .../delegate_component/statement/for_loop.rs | 71 +++++++------------ .../types/delegate_component/statement/mod.rs | 2 + 3 files changed, 90 insertions(+), 45 deletions(-) create mode 100644 crates/cgp-macro-core/src/types/delegate_component/statement/eval.rs diff --git a/crates/cgp-macro-core/src/types/delegate_component/statement/eval.rs b/crates/cgp-macro-core/src/types/delegate_component/statement/eval.rs new file mode 100644 index 00000000..c30d2d93 --- /dev/null +++ b/crates/cgp-macro-core/src/types/delegate_component/statement/eval.rs @@ -0,0 +1,62 @@ +use syn::{Generics, Ident, Type, parse_quote}; + +use crate::types::delegate_component::{EvalDelegateEntry, EvaluatedDelegateEntry}; +use crate::types::generics::TypeGenerics; + +pub trait EvalForEntry { + fn eval_for(&self, table_type: &Type) -> syn::Result>; +} + +pub struct EvaluatedForEntry { + pub generics: Generics, + pub table_type: Type, + pub for_key: Ident, + pub for_value: Ident, + pub namespace_ident: Ident, + pub namespace_generics: TypeGenerics, + pub mapping_key: Type, + pub mapping_value: Type, +} + +impl EvalDelegateEntry for EvaluatedForEntry { + fn eval(&self, _table_type: &Type) -> syn::Result> { + let for_key = &self.for_key; + let for_value = &self.for_value; + let mapping_value = &self.mapping_value; + let table_type = &self.table_type; + + let namespace_trait: Type = { + let namespace_ident = &self.namespace_ident; + let mut namespace_generics = self.namespace_generics.clone(); + + namespace_generics + .generics + .params + .push(parse_quote!(#table_type)); + + namespace_generics.generics.params.push(parse_quote! { + Provider = #mapping_value + }); + + parse_quote!( #namespace_ident #namespace_generics ) + }; + + let mut generics = self.generics.clone(); + generics.params.push(parse_quote!(#for_key)); + generics.params.push(parse_quote!(#for_value)); + + let where_clause = generics.make_where_clause(); + where_clause.predicates.push(parse_quote! { + #for_key: #namespace_trait + }); + + let entry = EvaluatedDelegateEntry { + table_type: table_type.clone(), + generics, + key: self.mapping_key.clone(), + value: self.mapping_value.clone(), + }; + + Ok(vec![entry]) + } +} diff --git a/crates/cgp-macro-core/src/types/delegate_component/statement/for_loop.rs b/crates/cgp-macro-core/src/types/delegate_component/statement/for_loop.rs index 07ebfd91..eb67f3f1 100644 --- a/crates/cgp-macro-core/src/types/delegate_component/statement/for_loop.rs +++ b/crates/cgp-macro-core/src/types/delegate_component/statement/for_loop.rs @@ -1,11 +1,11 @@ use syn::parse::{Parse, ParseStream}; use syn::punctuated::Punctuated; use syn::token::{Comma, For, Gt, In, Lt}; -use syn::{Ident, Type, WhereClause, braced, parse_quote}; +use syn::{Ident, Type, WhereClause, braced}; use crate::types::delegate_component::{ - EvalDelegateEntry, EvalDelegateKey, EvalDelegateValue, EvaluatedDelegateEntry, - NormalDelegateMapping, + EvalDelegateEntry, EvalDelegateKey, EvalDelegateValue, EvalForEntry, EvaluatedDelegateEntry, + EvaluatedForEntry, NormalDelegateMapping, }; use crate::types::ident_type::IdentType; @@ -56,19 +56,8 @@ impl Parse for ForDelegateStatement { } } -impl EvalDelegateEntry for ForDelegateStatement { - fn eval(&self, table_type: &Type) -> syn::Result> { - let for_key = &self.key; - let for_value = &self.value; - let for_where = &self.where_clause; - - let namespace_ident = &self.namespace.ident; - let mut namespace_generics = self.namespace.generics.clone(); - namespace_generics - .generics - .params - .push(parse_quote!(#table_type)); - +impl EvalForEntry for ForDelegateStatement { + fn eval_for(&self, table_type: &Type) -> syn::Result> { let mut entries = Vec::new(); for mapping in &self.mappings { @@ -76,36 +65,15 @@ impl EvalDelegateEntry for ForDelegateStatement { let value_type = mapping.value.eval()?; for key in keys { - let key_type = key.key; - let value_type = value_type.clone(); - - let namespace_trait: Type = { - let mut namespace_generics = namespace_generics.clone(); - namespace_generics.generics.params.push(parse_quote! { - Provider = #value_type - }); - - parse_quote!( #namespace_ident #namespace_generics ) - }; - - let mut generics = key.generics; - generics.params.push(parse_quote!(#for_key)); - generics.params.push(parse_quote!(#for_value)); - - let where_clause = generics.make_where_clause(); - where_clause.predicates.push(parse_quote! { - #for_key: #namespace_trait - }); - - if let Some(for_where) = for_where { - where_clause.predicates.extend(for_where.predicates.clone()); - } - - let entry = EvaluatedDelegateEntry { + let entry = EvaluatedForEntry { + generics: key.generics, table_type: table_type.clone(), - generics, - key: key_type, - value: value_type, + for_key: self.key.clone(), + for_value: self.value.clone(), + namespace_ident: self.namespace.ident.clone(), + namespace_generics: self.namespace.generics.clone(), + mapping_key: key.key, + mapping_value: value_type.clone(), }; entries.push(entry); @@ -115,3 +83,16 @@ impl EvalDelegateEntry for ForDelegateStatement { Ok(entries) } } + +impl EvalDelegateEntry for ForDelegateStatement { + fn eval(&self, table_type: &Type) -> syn::Result> { + let mut entries = Vec::new(); + + let for_entries = self.eval_for(table_type)?; + for for_entry in for_entries { + entries.extend(for_entry.eval(table_type)?); + } + + Ok(entries) + } +} diff --git a/crates/cgp-macro-core/src/types/delegate_component/statement/mod.rs b/crates/cgp-macro-core/src/types/delegate_component/statement/mod.rs index 5f4d608f..a33bf11f 100644 --- a/crates/cgp-macro-core/src/types/delegate_component/statement/mod.rs +++ b/crates/cgp-macro-core/src/types/delegate_component/statement/mod.rs @@ -1,9 +1,11 @@ mod combined; +mod eval; mod for_loop; mod namespace; mod open; pub use combined::*; +pub use eval::*; pub use for_loop::*; pub use namespace::*; pub use open::*; From 893f3535f6f9431d46bda4a4f37d9509591b2da0 Mon Sep 17 00:00:00 2001 From: Soares Chen Date: Mon, 25 May 2026 20:45:41 +0200 Subject: [PATCH 65/81] Implement EvalForEntry for NamespaceDelegateStatement --- .../delegate_component/statement/eval.rs | 17 ++++++++ .../delegate_component/statement/for_loop.rs | 11 +----- .../delegate_component/statement/namespace.rs | 39 +++++++++++-------- 3 files changed, 41 insertions(+), 26 deletions(-) diff --git a/crates/cgp-macro-core/src/types/delegate_component/statement/eval.rs b/crates/cgp-macro-core/src/types/delegate_component/statement/eval.rs index c30d2d93..6bc996bd 100644 --- a/crates/cgp-macro-core/src/types/delegate_component/statement/eval.rs +++ b/crates/cgp-macro-core/src/types/delegate_component/statement/eval.rs @@ -18,6 +18,23 @@ pub struct EvaluatedForEntry { pub mapping_value: Type, } +pub fn eval_delegate_entries_via_for( + entry: &Entry, + table_type: &Type, +) -> syn::Result> +where + Entry: EvalForEntry, +{ + let mut entries = Vec::new(); + + let for_entries = entry.eval_for(table_type)?; + for for_entry in for_entries { + entries.extend(for_entry.eval(table_type)?); + } + + Ok(entries) +} + impl EvalDelegateEntry for EvaluatedForEntry { fn eval(&self, _table_type: &Type) -> syn::Result> { let for_key = &self.for_key; diff --git a/crates/cgp-macro-core/src/types/delegate_component/statement/for_loop.rs b/crates/cgp-macro-core/src/types/delegate_component/statement/for_loop.rs index eb67f3f1..85e26dba 100644 --- a/crates/cgp-macro-core/src/types/delegate_component/statement/for_loop.rs +++ b/crates/cgp-macro-core/src/types/delegate_component/statement/for_loop.rs @@ -5,7 +5,7 @@ use syn::{Ident, Type, WhereClause, braced}; use crate::types::delegate_component::{ EvalDelegateEntry, EvalDelegateKey, EvalDelegateValue, EvalForEntry, EvaluatedDelegateEntry, - EvaluatedForEntry, NormalDelegateMapping, + EvaluatedForEntry, NormalDelegateMapping, eval_delegate_entries_via_for, }; use crate::types::ident_type::IdentType; @@ -86,13 +86,6 @@ impl EvalForEntry for ForDelegateStatement { impl EvalDelegateEntry for ForDelegateStatement { fn eval(&self, table_type: &Type) -> syn::Result> { - let mut entries = Vec::new(); - - let for_entries = self.eval_for(table_type)?; - for for_entry in for_entries { - entries.extend(for_entry.eval(table_type)?); - } - - Ok(entries) + eval_delegate_entries_via_for(self, table_type) } } diff --git a/crates/cgp-macro-core/src/types/delegate_component/statement/namespace.rs b/crates/cgp-macro-core/src/types/delegate_component/statement/namespace.rs index daad0198..e8aec5be 100644 --- a/crates/cgp-macro-core/src/types/delegate_component/statement/namespace.rs +++ b/crates/cgp-macro-core/src/types/delegate_component/statement/namespace.rs @@ -1,8 +1,12 @@ use syn::parse::{Parse, ParseStream}; use syn::token::Semi; -use syn::{Ident, Type, parse_quote}; +use syn::{Generics, Ident, Type, parse_quote}; -use crate::types::delegate_component::{EvalDelegateEntry, EvaluatedDelegateEntry}; +use crate::types::delegate_component::{ + EvalDelegateEntry, EvalForEntry, EvaluatedDelegateEntry, EvaluatedForEntry, + eval_delegate_entries_via_for, +}; +use crate::types::generics::TypeGenerics; use crate::types::keyword::Keyword; use crate::types::keywords::Namespace; @@ -27,30 +31,31 @@ impl Parse for NamespaceDelegateStatement { } } -impl EvalDelegateEntry for NamespaceDelegateStatement { - fn eval(&self, table_type: &Type) -> syn::Result> { +impl EvalForEntry for NamespaceDelegateStatement { + fn eval_for(&self, table_type: &Type) -> syn::Result> { let namespace_ident = if &self.ident == "default" { Ident::new("DefaultNamespace", self.ident.span()) } else { self.ident.clone() }; - let key = parse_quote!(__Component__); - let generics = parse_quote! { - <__Component__: #namespace_ident< #table_type >> - }; - - let value = parse_quote! { - < __Component__ as #namespace_ident< #table_type >>::Provider - }; - - let entry = EvaluatedDelegateEntry { + let entry = EvaluatedForEntry { + generics: Generics::default(), table_type: table_type.clone(), - generics, - key, - value, + for_key: parse_quote!(__Component__), + for_value: parse_quote!(__Provider__), + mapping_key: parse_quote!(__Component__), + mapping_value: parse_quote!(__Provider__), + namespace_ident, + namespace_generics: TypeGenerics::default(), }; Ok(vec![entry]) } } + +impl EvalDelegateEntry for NamespaceDelegateStatement { + fn eval(&self, table_type: &Type) -> syn::Result> { + eval_delegate_entries_via_for(self, table_type) + } +} From 8fd03a921434e0cf43df7929e1069a15d32c4c6e Mon Sep 17 00:00:00 2001 From: Soares Chen Date: Mon, 25 May 2026 21:15:15 +0200 Subject: [PATCH 66/81] Draft implement RedirectDelegateMapping --- .../types/delegate_component/mapping/mod.rs | 2 + .../delegate_component/mapping/normal.rs | 9 ++-- .../delegate_component/mapping/redirect.rs | 45 +++++++++++++++++++ crates/cgp-tests/src/namespaces/extended.rs | 1 + .../delegate_components/direct.rs | 6 ++- .../cgp-tests/tests/namespace_tests/open.rs | 3 +- 6 files changed, 59 insertions(+), 7 deletions(-) create mode 100644 crates/cgp-macro-core/src/types/delegate_component/mapping/redirect.rs diff --git a/crates/cgp-macro-core/src/types/delegate_component/mapping/mod.rs b/crates/cgp-macro-core/src/types/delegate_component/mapping/mod.rs index ae0c2709..cf054474 100644 --- a/crates/cgp-macro-core/src/types/delegate_component/mapping/mod.rs +++ b/crates/cgp-macro-core/src/types/delegate_component/mapping/mod.rs @@ -3,9 +3,11 @@ mod direct; mod eval; mod mode; mod normal; +mod redirect; pub use combined::*; pub use direct::*; pub use eval::*; pub use mode::*; pub use normal::*; +pub use redirect::*; diff --git a/crates/cgp-macro-core/src/types/delegate_component/mapping/normal.rs b/crates/cgp-macro-core/src/types/delegate_component/mapping/normal.rs index ae928ba4..e476d002 100644 --- a/crates/cgp-macro-core/src/types/delegate_component/mapping/normal.rs +++ b/crates/cgp-macro-core/src/types/delegate_component/mapping/normal.rs @@ -29,15 +29,16 @@ impl EvalDelegateEntry for NormalDelegateMapping { let keys = self.key.eval()?; let value_type = self.value.eval()?; - let entries = keys - .into_iter() - .map(|key| EvaluatedDelegateEntry { + let mut entries = Vec::new(); + + for key in keys { + entries.push(EvaluatedDelegateEntry { table_type: table_type.clone(), generics: key.generics, key: key.key, value: value_type.clone(), }) - .collect(); + } Ok(entries) } diff --git a/crates/cgp-macro-core/src/types/delegate_component/mapping/redirect.rs b/crates/cgp-macro-core/src/types/delegate_component/mapping/redirect.rs new file mode 100644 index 00000000..3b2c9829 --- /dev/null +++ b/crates/cgp-macro-core/src/types/delegate_component/mapping/redirect.rs @@ -0,0 +1,45 @@ +use syn::token::FatArrow; +use syn::{Type, parse_quote}; + +use crate::types::delegate_component::{ + DelegateKey, EvalDelegateEntry, EvalDelegateKey, EvaluatedDelegateEntry, +}; +use crate::types::path::UniPath; + +pub struct RedirectDelegateMapping { + pub key: DelegateKey, + pub arrow: FatArrow, + pub value: UniPath, +} + +impl EvalDelegateEntry for RedirectDelegateMapping { + fn eval(&self, table_type: &Type) -> syn::Result> { + let value_type: Type = match &self.key { + DelegateKey::Path(_) => { + let prefix = self.value.clone().to_prefix(parse_quote!(__Wildcard__)); + parse_quote! { + RedirectLookup<#prefix> + } + } + _ => { + let path = &self.value; + parse_quote!(RedirectLookup<#path>) + } + }; + + let mut entries = Vec::new(); + + for key in self.key.eval()? { + let entry = EvaluatedDelegateEntry { + table_type: table_type.clone(), + generics: key.generics, + key: key.key, + value: value_type.clone(), + }; + + entries.push(entry); + } + + Ok(entries) + } +} diff --git a/crates/cgp-tests/src/namespaces/extended.rs b/crates/cgp-tests/src/namespaces/extended.rs index bae6e595..dc681c97 100644 --- a/crates/cgp-tests/src/namespaces/extended.rs +++ b/crates/cgp-tests/src/namespaces/extended.rs @@ -3,6 +3,7 @@ use cgp::prelude::*; cgp_namespace! { ExtendedNamespace: DefaultNamespace { + // @cgp.core.error >> @app, @cgp.core.error: @app, } diff --git a/crates/cgp-tests/tests/component_tests/delegate_components/direct.rs b/crates/cgp-tests/tests/component_tests/delegate_components/direct.rs index e068aca1..c5017a8b 100644 --- a/crates/cgp-tests/tests/component_tests/delegate_components/direct.rs +++ b/crates/cgp-tests/tests/component_tests/delegate_components/direct.rs @@ -9,8 +9,10 @@ delegate_components! { delegate_components! { new BarComponents { - Index<0>: FooComponents, - Index<1> -> FooComponents, + Index<0>: + FooComponents, + Index<1> -> + FooComponents, } } diff --git a/crates/cgp-tests/tests/namespace_tests/open.rs b/crates/cgp-tests/tests/namespace_tests/open.rs index 52fe6818..c528de71 100644 --- a/crates/cgp-tests/tests/namespace_tests/open.rs +++ b/crates/cgp-tests/tests/namespace_tests/open.rs @@ -24,7 +24,8 @@ impl BarProvider { delegate_components! { App { - // FooProviderComponent => @FooProviderComponent, + // FooProviderComponent => + // @FooProviderComponent, open {FooProviderComponent, BarProviderComponent}; @FooProviderComponent.String: From d8f9797bfec4b43523553f045d9ea7e8bef74be5 Mon Sep 17 00:00:00 2001 From: Soares Chen Date: Mon, 25 May 2026 21:23:59 +0200 Subject: [PATCH 67/81] Redirect mapping is working --- .../src/types/delegate_component/mapping/combined.rs | 12 ++++++++++-- .../src/types/delegate_component/mapping/mode.rs | 5 ++++- .../src/types/delegate_component/mapping/redirect.rs | 6 ++++-- crates/cgp-tests/tests/namespace_tests/open.rs | 5 ++++- 4 files changed, 22 insertions(+), 6 deletions(-) diff --git a/crates/cgp-macro-core/src/types/delegate_component/mapping/combined.rs b/crates/cgp-macro-core/src/types/delegate_component/mapping/combined.rs index 0f53d885..f32e1ea9 100644 --- a/crates/cgp-macro-core/src/types/delegate_component/mapping/combined.rs +++ b/crates/cgp-macro-core/src/types/delegate_component/mapping/combined.rs @@ -3,28 +3,34 @@ use syn::parse::{Parse, ParseStream}; use crate::types::delegate_component::{ DelegateMode, DirectDelegateMapping, EvalDelegateEntry, EvaluatedDelegateEntry, - ExtractInnerDelegateTables, InnerDelegateTable, NormalDelegateMapping, + ExtractInnerDelegateTables, InnerDelegateTable, NormalDelegateMapping, RedirectDelegateMapping, }; #[derive(Debug, Clone)] pub enum DelegateMapping { Normal(NormalDelegateMapping), Direct(DirectDelegateMapping), + Redirect(RedirectDelegateMapping), } impl Parse for DelegateMapping { fn parse(input: ParseStream) -> syn::Result { let key = input.parse()?; let mode: DelegateMode = input.parse()?; - let value = input.parse()?; let entry = match mode { DelegateMode::Normal(colon) => { + let value = input.parse()?; Self::Normal(NormalDelegateMapping { key, colon, value }) } DelegateMode::Direct(arrow) => { + let value = input.parse()?; Self::Direct(DirectDelegateMapping { key, arrow, value }) } + DelegateMode::Redirect(arrow) => { + let value = input.parse()?; + Self::Redirect(RedirectDelegateMapping { key, arrow, value }) + } }; Ok(entry) @@ -36,6 +42,7 @@ impl EvalDelegateEntry for DelegateMapping { match self { Self::Normal(entry) => entry.eval(table_type), Self::Direct(entry) => entry.eval(table_type), + Self::Redirect(entry) => entry.eval(table_type), } } } @@ -45,6 +52,7 @@ impl ExtractInnerDelegateTables for DelegateMapping { match self { Self::Normal(entry) => entry.extract_inner_tables(), Self::Direct(entry) => entry.extract_inner_tables(), + Self::Redirect(_entry) => Vec::new(), } } } diff --git a/crates/cgp-macro-core/src/types/delegate_component/mapping/mode.rs b/crates/cgp-macro-core/src/types/delegate_component/mapping/mode.rs index 5fb21d48..eb8e9b8e 100644 --- a/crates/cgp-macro-core/src/types/delegate_component/mapping/mode.rs +++ b/crates/cgp-macro-core/src/types/delegate_component/mapping/mode.rs @@ -1,15 +1,18 @@ use syn::parse::{Parse, ParseStream}; -use syn::token::{Colon, RArrow}; +use syn::token::{Colon, FatArrow, RArrow}; pub enum DelegateMode { Normal(Colon), Direct(RArrow), + Redirect(FatArrow), } impl Parse for DelegateMode { fn parse(input: ParseStream) -> syn::Result { if input.peek(RArrow) { Ok(Self::Direct(input.parse()?)) + } else if input.peek(FatArrow) { + Ok(Self::Redirect(input.parse()?)) } else { Ok(Self::Normal(input.parse()?)) } diff --git a/crates/cgp-macro-core/src/types/delegate_component/mapping/redirect.rs b/crates/cgp-macro-core/src/types/delegate_component/mapping/redirect.rs index 3b2c9829..d14fc677 100644 --- a/crates/cgp-macro-core/src/types/delegate_component/mapping/redirect.rs +++ b/crates/cgp-macro-core/src/types/delegate_component/mapping/redirect.rs @@ -1,11 +1,13 @@ use syn::token::FatArrow; use syn::{Type, parse_quote}; +use crate::exports::RedirectLookup; use crate::types::delegate_component::{ DelegateKey, EvalDelegateEntry, EvalDelegateKey, EvaluatedDelegateEntry, }; use crate::types::path::UniPath; +#[derive(Debug, Clone)] pub struct RedirectDelegateMapping { pub key: DelegateKey, pub arrow: FatArrow, @@ -18,12 +20,12 @@ impl EvalDelegateEntry for RedirectDelegateMapping { DelegateKey::Path(_) => { let prefix = self.value.clone().to_prefix(parse_quote!(__Wildcard__)); parse_quote! { - RedirectLookup<#prefix> + #RedirectLookup<#table_type, #prefix> } } _ => { let path = &self.value; - parse_quote!(RedirectLookup<#path>) + parse_quote!(#RedirectLookup<#table_type, #path>) } }; diff --git a/crates/cgp-tests/tests/namespace_tests/open.rs b/crates/cgp-tests/tests/namespace_tests/open.rs index c528de71..21c7f9cd 100644 --- a/crates/cgp-tests/tests/namespace_tests/open.rs +++ b/crates/cgp-tests/tests/namespace_tests/open.rs @@ -24,9 +24,12 @@ impl BarProvider { delegate_components! { App { + open {FooProviderComponent, BarProviderComponent}; + // FooProviderComponent => // @FooProviderComponent, - open {FooProviderComponent, BarProviderComponent}; + // BarProviderComponent => + // @BarProviderComponent, @FooProviderComponent.String: DummyFoo, From 5f07f6fec762e93a69ddcaf2e2857244f85fa06b Mon Sep 17 00:00:00 2001 From: Soares Chen Date: Mon, 25 May 2026 22:52:22 +0200 Subject: [PATCH 68/81] Draft implement NamespaceTable --- .../src/types/delegate_component/entries.rs | 27 ++++-- .../types/delegate_component/mapping/eval.rs | 23 +++++ .../src/types/delegate_component/table/mod.rs | 2 + .../delegate_component/table/namespace.rs | 93 +++++++++++++++++++ .../src/types/generics/type_generics.rs | 8 +- 5 files changed, 144 insertions(+), 9 deletions(-) create mode 100644 crates/cgp-macro-core/src/types/delegate_component/table/namespace.rs diff --git a/crates/cgp-macro-core/src/types/delegate_component/entries.rs b/crates/cgp-macro-core/src/types/delegate_component/entries.rs index e4bed06b..b7c14711 100644 --- a/crates/cgp-macro-core/src/types/delegate_component/entries.rs +++ b/crates/cgp-macro-core/src/types/delegate_component/entries.rs @@ -32,24 +32,35 @@ impl Parse for DelegateEntries { } } -impl DelegateEntries { - pub fn build_impls( +impl EvalDelegateEntry for DelegateEntries { + fn eval( &self, table_type: &Type, - outer_generics: &Generics, - ) -> syn::Result> { - let mut item_impls = Vec::new(); - + ) -> syn::Result> { let mut evaluated_entries = Vec::new(); for statement in &self.statements { - evaluated_entries.extend(statement.eval(&table_type)?); + evaluated_entries.extend(statement.eval(table_type)?); } for entry in &self.entries { - evaluated_entries.extend(entry.eval(&table_type)?); + evaluated_entries.extend(entry.eval(table_type)?); } + Ok(evaluated_entries) + } +} + +impl DelegateEntries { + pub fn build_impls( + &self, + table_type: &Type, + outer_generics: &Generics, + ) -> syn::Result> { + let mut item_impls = Vec::new(); + + let evaluated_entries = self.eval(table_type)?; + for evaluated_entry in evaluated_entries { let delegate_component_impl = evaluated_entry.build_delegate_component_impl(outer_generics)?; diff --git a/crates/cgp-macro-core/src/types/delegate_component/mapping/eval.rs b/crates/cgp-macro-core/src/types/delegate_component/mapping/eval.rs index 28d570b4..421feb6b 100644 --- a/crates/cgp-macro-core/src/types/delegate_component/mapping/eval.rs +++ b/crates/cgp-macro-core/src/types/delegate_component/mapping/eval.rs @@ -65,4 +65,27 @@ impl EvaluatedDelegateEntry { {} }) } + + pub fn build_namespace_impl( + &self, + namespace_trait: &Type, + outer_generics: &Generics, + ) -> syn::Result { + let generics = merge_generics(outer_generics, &self.generics); + + let key = &self.key; + let value = &self.value; + + let (impl_generics, _, where_clause) = generics.split_for_impl(); + + parse2(quote! { + impl #impl_generics + #namespace_trait + for #key + #where_clause + { + type Delegate = #value; + } + }) + } } diff --git a/crates/cgp-macro-core/src/types/delegate_component/table/mod.rs b/crates/cgp-macro-core/src/types/delegate_component/table/mod.rs index 0e43a88d..297665bc 100644 --- a/crates/cgp-macro-core/src/types/delegate_component/table/mod.rs +++ b/crates/cgp-macro-core/src/types/delegate_component/table/mod.rs @@ -1,5 +1,7 @@ mod inner; mod main; +mod namespace; pub use inner::*; pub use main::*; +pub use namespace::*; diff --git a/crates/cgp-macro-core/src/types/delegate_component/table/namespace.rs b/crates/cgp-macro-core/src/types/delegate_component/table/namespace.rs new file mode 100644 index 00000000..b5cabff5 --- /dev/null +++ b/crates/cgp-macro-core/src/types/delegate_component/table/namespace.rs @@ -0,0 +1,93 @@ +use syn::parse::{Parse, ParseStream}; +use syn::{Ident, ItemImpl, ItemTrait, Type, braced, parse_quote}; + +use crate::traits::PeekKeyword; +use crate::types::delegate_component::{DelegateEntries, EvalDelegateEntry}; +use crate::types::generics::{ImplGenerics, TypeGenerics}; +use crate::types::keyword::Keyword; +use crate::types::keywords::New; + +pub struct NamespaceTable { + pub impl_generics: ImplGenerics, + pub new: Option>, + pub namespace_ident: Ident, + pub namespace_generics: TypeGenerics, + pub entries: DelegateEntries, +} + +pub struct EvaluatedNamespaceTable { + pub item_impls: Vec, + pub item_trait: Option, +} + +impl Parse for NamespaceTable { + fn parse(input: ParseStream) -> syn::Result { + let impl_generics = input.parse()?; + + let new = if input.peek_keyword::() { + Some(input.parse()?) + } else { + None + }; + + let namespace_ident = input.parse()?; + let namespace_generics = input.parse()?; + + let entries = { + let body; + braced!(body in input); + + body.parse()? + }; + + Ok(Self { + impl_generics, + new, + namespace_ident, + namespace_generics, + entries, + }) + } +} + +impl NamespaceTable { + pub fn eval(&self) -> syn::Result { + let namespace_ident = &self.namespace_ident; + + let mut namespace_generics = self.namespace_generics.clone(); + namespace_generics.params.push(parse_quote!(__Components__)); + + let item_trait: Option = if self.new.is_some() { + let item_trait = parse_quote! { + pub trait #namespace_ident #namespace_generics { + type Provider; + } + }; + + Some(item_trait) + } else { + None + }; + + let mut impl_generics = self.impl_generics.clone(); + impl_generics.params.push(parse_quote!(__Components__)); + + let namespace_trait: Type = parse_quote!( #namespace_ident #namespace_generics ); + let table_type: Type = parse_quote!(__Components__); + + let evaluated_entries = self.entries.eval(&table_type)?; + + let mut item_impls: Vec = Vec::new(); + + for evaluated_entry in evaluated_entries { + let item_impl = + evaluated_entry.build_namespace_impl(&namespace_trait, &impl_generics)?; + item_impls.push(item_impl); + } + + Ok(EvaluatedNamespaceTable { + item_impls, + item_trait, + }) + } +} diff --git a/crates/cgp-macro-core/src/types/generics/type_generics.rs b/crates/cgp-macro-core/src/types/generics/type_generics.rs index 22289b01..4924f0d3 100644 --- a/crates/cgp-macro-core/src/types/generics/type_generics.rs +++ b/crates/cgp-macro-core/src/types/generics/type_generics.rs @@ -1,4 +1,4 @@ -use core::ops::Deref; +use core::ops::{Deref, DerefMut}; use proc_macro2::TokenStream; use quote::ToTokens; @@ -18,6 +18,12 @@ impl Deref for TypeGenerics { } } +impl DerefMut for TypeGenerics { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.generics + } +} + impl Parse for TypeGenerics { fn parse(input: ParseStream) -> syn::Result { let generics: Generics = input.parse()?; From e23ca0db3e890f6aeaf7a2f9a2ae94bad13ee01a Mon Sep 17 00:00:00 2001 From: Soares Chen Date: Mon, 25 May 2026 23:32:35 +0200 Subject: [PATCH 69/81] Handle parent namespace --- .../src/types/delegate_component/entries.rs | 12 +- .../delegate_component/mapping/combined.rs | 12 +- .../delegate_component/mapping/direct.rs | 6 +- .../types/delegate_component/mapping/eval.rs | 8 +- .../delegate_component/mapping/normal.rs | 6 +- .../delegate_component/mapping/redirect.rs | 6 +- .../delegate_component/statement/combined.rs | 12 +- .../delegate_component/statement/eval.rs | 10 +- .../delegate_component/statement/for_loop.rs | 6 +- .../delegate_component/statement/namespace.rs | 7 +- .../delegate_component/statement/open.rs | 6 +- .../delegate_component/table/namespace.rs | 126 ++++++++++++++++-- crates/cgp-macro-core/src/types/keyword.rs | 9 ++ .../src/entrypoints/cgp_namespace.rs | 5 + crates/cgp-tests/src/namespaces/extended.rs | 10 ++ 15 files changed, 186 insertions(+), 55 deletions(-) diff --git a/crates/cgp-macro-core/src/types/delegate_component/entries.rs b/crates/cgp-macro-core/src/types/delegate_component/entries.rs index b7c14711..919ad512 100644 --- a/crates/cgp-macro-core/src/types/delegate_component/entries.rs +++ b/crates/cgp-macro-core/src/types/delegate_component/entries.rs @@ -4,7 +4,7 @@ use syn::token::Comma; use syn::{Generics, ItemImpl, Type}; use crate::types::delegate_component::{ - DelegateMapping, DelegateStatement, EvalDelegateEntry, ExtractInnerDelegateTables, + DelegateMapping, DelegateStatement, EvalDelegateEntries, ExtractInnerDelegateTables, InnerDelegateTable, }; @@ -32,19 +32,19 @@ impl Parse for DelegateEntries { } } -impl EvalDelegateEntry for DelegateEntries { - fn eval( +impl EvalDelegateEntries for DelegateEntries { + fn eval_entries( &self, table_type: &Type, ) -> syn::Result> { let mut evaluated_entries = Vec::new(); for statement in &self.statements { - evaluated_entries.extend(statement.eval(table_type)?); + evaluated_entries.extend(statement.eval_entries(table_type)?); } for entry in &self.entries { - evaluated_entries.extend(entry.eval(table_type)?); + evaluated_entries.extend(entry.eval_entries(table_type)?); } Ok(evaluated_entries) @@ -59,7 +59,7 @@ impl DelegateEntries { ) -> syn::Result> { let mut item_impls = Vec::new(); - let evaluated_entries = self.eval(table_type)?; + let evaluated_entries = self.eval_entries(table_type)?; for evaluated_entry in evaluated_entries { let delegate_component_impl = diff --git a/crates/cgp-macro-core/src/types/delegate_component/mapping/combined.rs b/crates/cgp-macro-core/src/types/delegate_component/mapping/combined.rs index f32e1ea9..7a1a8354 100644 --- a/crates/cgp-macro-core/src/types/delegate_component/mapping/combined.rs +++ b/crates/cgp-macro-core/src/types/delegate_component/mapping/combined.rs @@ -2,7 +2,7 @@ use syn::Type; use syn::parse::{Parse, ParseStream}; use crate::types::delegate_component::{ - DelegateMode, DirectDelegateMapping, EvalDelegateEntry, EvaluatedDelegateEntry, + DelegateMode, DirectDelegateMapping, EvalDelegateEntries, EvaluatedDelegateEntry, ExtractInnerDelegateTables, InnerDelegateTable, NormalDelegateMapping, RedirectDelegateMapping, }; @@ -37,12 +37,12 @@ impl Parse for DelegateMapping { } } -impl EvalDelegateEntry for DelegateMapping { - fn eval(&self, table_type: &Type) -> syn::Result> { +impl EvalDelegateEntries for DelegateMapping { + fn eval_entries(&self, table_type: &Type) -> syn::Result> { match self { - Self::Normal(entry) => entry.eval(table_type), - Self::Direct(entry) => entry.eval(table_type), - Self::Redirect(entry) => entry.eval(table_type), + Self::Normal(entry) => entry.eval_entries(table_type), + Self::Direct(entry) => entry.eval_entries(table_type), + Self::Redirect(entry) => entry.eval_entries(table_type), } } } diff --git a/crates/cgp-macro-core/src/types/delegate_component/mapping/direct.rs b/crates/cgp-macro-core/src/types/delegate_component/mapping/direct.rs index 9ee19ce3..e27694de 100644 --- a/crates/cgp-macro-core/src/types/delegate_component/mapping/direct.rs +++ b/crates/cgp-macro-core/src/types/delegate_component/mapping/direct.rs @@ -3,7 +3,7 @@ use syn::{Type, parse_quote}; use crate::exports::DelegateComponent; use crate::types::delegate_component::{ - DelegateKey, DelegateValue, EvalDelegateEntry, EvalDelegateKey, EvalDelegateValue, + DelegateKey, DelegateValue, EvalDelegateEntries, EvalDelegateKey, EvalDelegateValue, EvaluatedDelegateEntry, ExtractInnerDelegateTables, InnerDelegateTable, }; @@ -14,8 +14,8 @@ pub struct DirectDelegateMapping { pub value: DelegateValue, } -impl EvalDelegateEntry for DirectDelegateMapping { - fn eval(&self, table_type: &Type) -> syn::Result> { +impl EvalDelegateEntries for DirectDelegateMapping { + fn eval_entries(&self, table_type: &Type) -> syn::Result> { let keys = self.key.eval()?; let value_type = self.value.eval()?; diff --git a/crates/cgp-macro-core/src/types/delegate_component/mapping/eval.rs b/crates/cgp-macro-core/src/types/delegate_component/mapping/eval.rs index 421feb6b..04de4520 100644 --- a/crates/cgp-macro-core/src/types/delegate_component/mapping/eval.rs +++ b/crates/cgp-macro-core/src/types/delegate_component/mapping/eval.rs @@ -12,7 +12,11 @@ pub struct EvaluatedDelegateEntry { } pub trait EvalDelegateEntry { - fn eval(&self, table_type: &Type) -> syn::Result>; + fn eval_entry(&self, table_type: &Type) -> syn::Result; +} + +pub trait EvalDelegateEntries { + fn eval_entries(&self, table_type: &Type) -> syn::Result>; } impl EvaluatedDelegateEntry { @@ -84,7 +88,7 @@ impl EvaluatedDelegateEntry { for #key #where_clause { - type Delegate = #value; + type Provider = #value; } }) } diff --git a/crates/cgp-macro-core/src/types/delegate_component/mapping/normal.rs b/crates/cgp-macro-core/src/types/delegate_component/mapping/normal.rs index e476d002..7c036cef 100644 --- a/crates/cgp-macro-core/src/types/delegate_component/mapping/normal.rs +++ b/crates/cgp-macro-core/src/types/delegate_component/mapping/normal.rs @@ -3,7 +3,7 @@ use syn::parse::{Parse, ParseStream}; use syn::token::Colon; use crate::types::delegate_component::{ - DelegateKey, DelegateValue, EvalDelegateEntry, EvalDelegateKey, EvalDelegateValue, + DelegateKey, DelegateValue, EvalDelegateEntries, EvalDelegateKey, EvalDelegateValue, EvaluatedDelegateEntry, ExtractInnerDelegateTables, InnerDelegateTable, }; @@ -24,8 +24,8 @@ impl Parse for NormalDelegateMapping { } } -impl EvalDelegateEntry for NormalDelegateMapping { - fn eval(&self, table_type: &Type) -> syn::Result> { +impl EvalDelegateEntries for NormalDelegateMapping { + fn eval_entries(&self, table_type: &Type) -> syn::Result> { let keys = self.key.eval()?; let value_type = self.value.eval()?; diff --git a/crates/cgp-macro-core/src/types/delegate_component/mapping/redirect.rs b/crates/cgp-macro-core/src/types/delegate_component/mapping/redirect.rs index d14fc677..5e3f1558 100644 --- a/crates/cgp-macro-core/src/types/delegate_component/mapping/redirect.rs +++ b/crates/cgp-macro-core/src/types/delegate_component/mapping/redirect.rs @@ -3,7 +3,7 @@ use syn::{Type, parse_quote}; use crate::exports::RedirectLookup; use crate::types::delegate_component::{ - DelegateKey, EvalDelegateEntry, EvalDelegateKey, EvaluatedDelegateEntry, + DelegateKey, EvalDelegateEntries, EvalDelegateKey, EvaluatedDelegateEntry, }; use crate::types::path::UniPath; @@ -14,8 +14,8 @@ pub struct RedirectDelegateMapping { pub value: UniPath, } -impl EvalDelegateEntry for RedirectDelegateMapping { - fn eval(&self, table_type: &Type) -> syn::Result> { +impl EvalDelegateEntries for RedirectDelegateMapping { + fn eval_entries(&self, table_type: &Type) -> syn::Result> { let value_type: Type = match &self.key { DelegateKey::Path(_) => { let prefix = self.value.clone().to_prefix(parse_quote!(__Wildcard__)); diff --git a/crates/cgp-macro-core/src/types/delegate_component/statement/combined.rs b/crates/cgp-macro-core/src/types/delegate_component/statement/combined.rs index dd5f53d6..a1ea5935 100644 --- a/crates/cgp-macro-core/src/types/delegate_component/statement/combined.rs +++ b/crates/cgp-macro-core/src/types/delegate_component/statement/combined.rs @@ -4,7 +4,7 @@ use syn::{Error, Type}; use crate::traits::PeekKeyword; use crate::types::delegate_component::{ - EvalDelegateEntry, EvaluatedDelegateEntry, ForDelegateStatement, NamespaceDelegateStatement, + EvalDelegateEntries, EvaluatedDelegateEntry, ForDelegateStatement, NamespaceDelegateStatement, OpenDelegateStatement, }; use crate::types::keywords::{Namespace, Open}; @@ -39,12 +39,12 @@ impl Parse for DelegateStatement { } } -impl EvalDelegateEntry for DelegateStatement { - fn eval(&self, table_type: &Type) -> syn::Result> { +impl EvalDelegateEntries for DelegateStatement { + fn eval_entries(&self, table_type: &Type) -> syn::Result> { match self { - Self::Namespace(entry) => entry.eval(table_type), - Self::Open(entry) => entry.eval(table_type), - Self::For(entry) => entry.eval(table_type), + Self::Namespace(entry) => entry.eval_entries(table_type), + Self::Open(entry) => entry.eval_entries(table_type), + Self::For(entry) => entry.eval_entries(table_type), } } } diff --git a/crates/cgp-macro-core/src/types/delegate_component/statement/eval.rs b/crates/cgp-macro-core/src/types/delegate_component/statement/eval.rs index 6bc996bd..bbd5c5f8 100644 --- a/crates/cgp-macro-core/src/types/delegate_component/statement/eval.rs +++ b/crates/cgp-macro-core/src/types/delegate_component/statement/eval.rs @@ -1,6 +1,8 @@ use syn::{Generics, Ident, Type, parse_quote}; -use crate::types::delegate_component::{EvalDelegateEntry, EvaluatedDelegateEntry}; +use crate::types::delegate_component::{ + EvalDelegateEntry, EvaluatedDelegateEntry, +}; use crate::types::generics::TypeGenerics; pub trait EvalForEntry { @@ -29,14 +31,14 @@ where let for_entries = entry.eval_for(table_type)?; for for_entry in for_entries { - entries.extend(for_entry.eval(table_type)?); + entries.push(for_entry.eval_entry(table_type)?); } Ok(entries) } impl EvalDelegateEntry for EvaluatedForEntry { - fn eval(&self, _table_type: &Type) -> syn::Result> { + fn eval_entry(&self, _table_type: &Type) -> syn::Result { let for_key = &self.for_key; let for_value = &self.for_value; let mapping_value = &self.mapping_value; @@ -74,6 +76,6 @@ impl EvalDelegateEntry for EvaluatedForEntry { value: self.mapping_value.clone(), }; - Ok(vec![entry]) + Ok(entry) } } diff --git a/crates/cgp-macro-core/src/types/delegate_component/statement/for_loop.rs b/crates/cgp-macro-core/src/types/delegate_component/statement/for_loop.rs index 85e26dba..bb8bb22e 100644 --- a/crates/cgp-macro-core/src/types/delegate_component/statement/for_loop.rs +++ b/crates/cgp-macro-core/src/types/delegate_component/statement/for_loop.rs @@ -4,7 +4,7 @@ use syn::token::{Comma, For, Gt, In, Lt}; use syn::{Ident, Type, WhereClause, braced}; use crate::types::delegate_component::{ - EvalDelegateEntry, EvalDelegateKey, EvalDelegateValue, EvalForEntry, EvaluatedDelegateEntry, + EvalDelegateEntries, EvalDelegateKey, EvalDelegateValue, EvalForEntry, EvaluatedDelegateEntry, EvaluatedForEntry, NormalDelegateMapping, eval_delegate_entries_via_for, }; use crate::types::ident_type::IdentType; @@ -84,8 +84,8 @@ impl EvalForEntry for ForDelegateStatement { } } -impl EvalDelegateEntry for ForDelegateStatement { - fn eval(&self, table_type: &Type) -> syn::Result> { +impl EvalDelegateEntries for ForDelegateStatement { + fn eval_entries(&self, table_type: &Type) -> syn::Result> { eval_delegate_entries_via_for(self, table_type) } } diff --git a/crates/cgp-macro-core/src/types/delegate_component/statement/namespace.rs b/crates/cgp-macro-core/src/types/delegate_component/statement/namespace.rs index e8aec5be..7ac18e05 100644 --- a/crates/cgp-macro-core/src/types/delegate_component/statement/namespace.rs +++ b/crates/cgp-macro-core/src/types/delegate_component/statement/namespace.rs @@ -3,7 +3,7 @@ use syn::token::Semi; use syn::{Generics, Ident, Type, parse_quote}; use crate::types::delegate_component::{ - EvalDelegateEntry, EvalForEntry, EvaluatedDelegateEntry, EvaluatedForEntry, + EvalDelegateEntries, EvalForEntry, EvaluatedDelegateEntry, EvaluatedForEntry, eval_delegate_entries_via_for, }; use crate::types::generics::TypeGenerics; @@ -14,6 +14,7 @@ use crate::types::keywords::Namespace; pub struct NamespaceDelegateStatement { pub namespace: Keyword, pub ident: Ident, + pub semi: Semi, } @@ -54,8 +55,8 @@ impl EvalForEntry for NamespaceDelegateStatement { } } -impl EvalDelegateEntry for NamespaceDelegateStatement { - fn eval(&self, table_type: &Type) -> syn::Result> { +impl EvalDelegateEntries for NamespaceDelegateStatement { + fn eval_entries(&self, table_type: &Type) -> syn::Result> { eval_delegate_entries_via_for(self, table_type) } } diff --git a/crates/cgp-macro-core/src/types/delegate_component/statement/open.rs b/crates/cgp-macro-core/src/types/delegate_component/statement/open.rs index c00555b7..29f99539 100644 --- a/crates/cgp-macro-core/src/types/delegate_component/statement/open.rs +++ b/crates/cgp-macro-core/src/types/delegate_component/statement/open.rs @@ -4,7 +4,7 @@ use syn::token::{Comma, Semi}; use syn::{Type, braced, parse_quote}; use crate::exports::{Nil, PathCons, RedirectLookup}; -use crate::types::delegate_component::{EvalDelegateEntry, EvaluatedDelegateEntry}; +use crate::types::delegate_component::{EvalDelegateEntries, EvaluatedDelegateEntry}; use crate::types::keyword::Keyword; use crate::types::keywords::Open; @@ -36,8 +36,8 @@ impl Parse for OpenDelegateStatement { } } -impl EvalDelegateEntry for OpenDelegateStatement { - fn eval(&self, table_type: &Type) -> syn::Result> { +impl EvalDelegateEntries for OpenDelegateStatement { + fn eval_entries(&self, table_type: &Type) -> syn::Result> { let mut entries = Vec::new(); for component in &self.components { diff --git a/crates/cgp-macro-core/src/types/delegate_component/table/namespace.rs b/crates/cgp-macro-core/src/types/delegate_component/table/namespace.rs index b5cabff5..d88729e0 100644 --- a/crates/cgp-macro-core/src/types/delegate_component/table/namespace.rs +++ b/crates/cgp-macro-core/src/types/delegate_component/table/namespace.rs @@ -1,17 +1,23 @@ +use proc_macro2::TokenStream; +use quote::ToTokens; use syn::parse::{Parse, ParseStream}; -use syn::{Ident, ItemImpl, ItemTrait, Type, braced, parse_quote}; +use syn::token::Colon; +use syn::{Ident, ItemImpl, ItemStruct, ItemTrait, Type, braced, parse_quote}; use crate::traits::PeekKeyword; -use crate::types::delegate_component::{DelegateEntries, EvalDelegateEntry}; +use crate::types::delegate_component::{ + DelegateEntries, EvalDelegateEntries, EvalDelegateEntry, EvaluatedForEntry, +}; use crate::types::generics::{ImplGenerics, TypeGenerics}; +use crate::types::ident_type::IdentType; use crate::types::keyword::Keyword; use crate::types::keywords::New; pub struct NamespaceTable { pub impl_generics: ImplGenerics, pub new: Option>, - pub namespace_ident: Ident, - pub namespace_generics: TypeGenerics, + pub namespace_type: IdentType, + pub parent_namespace: Option<(Colon, IdentType)>, pub entries: DelegateEntries, } @@ -30,8 +36,14 @@ impl Parse for NamespaceTable { None }; - let namespace_ident = input.parse()?; - let namespace_generics = input.parse()?; + let namespace_type = input.parse()?; + let parent_namespace = if input.peek(Colon) { + let colon: Colon = input.parse()?; + let parent_namespace_type = input.parse()?; + Some((colon, parent_namespace_type)) + } else { + None + }; let entries = { let body; @@ -43,18 +55,18 @@ impl Parse for NamespaceTable { Ok(Self { impl_generics, new, - namespace_ident, - namespace_generics, + namespace_type, + parent_namespace, entries, }) } } impl NamespaceTable { - pub fn eval(&self) -> syn::Result { - let namespace_ident = &self.namespace_ident; + pub fn build_item_trait(&self) -> syn::Result> { + let namespace_ident = &self.namespace_type.ident; - let mut namespace_generics = self.namespace_generics.clone(); + let mut namespace_generics = self.namespace_type.generics.clone(); namespace_generics.params.push(parse_quote!(__Components__)); let item_trait: Option = if self.new.is_some() { @@ -69,13 +81,32 @@ impl NamespaceTable { None }; + Ok(item_trait) + } + + pub fn build_namespace_generics(&self) -> syn::Result { + let mut namespace_generics = self.namespace_type.generics.clone(); + namespace_generics.params.push(parse_quote!(__Components__)); + + Ok(namespace_generics) + } + + pub fn build_namespace_trait(&self) -> syn::Result { + let namespace_ident = &self.namespace_type.ident; + let namespace_generics = self.build_namespace_generics()?; + + let namespace_trait: Type = parse_quote!( #namespace_ident #namespace_generics ); + Ok(namespace_trait) + } + + pub fn build_item_impls(&self) -> syn::Result> { let mut impl_generics = self.impl_generics.clone(); impl_generics.params.push(parse_quote!(__Components__)); - let namespace_trait: Type = parse_quote!( #namespace_ident #namespace_generics ); + let namespace_trait = self.build_namespace_trait()?; let table_type: Type = parse_quote!(__Components__); - let evaluated_entries = self.entries.eval(&table_type)?; + let evaluated_entries = self.entries.eval_entries(&table_type)?; let mut item_impls: Vec = Vec::new(); @@ -85,9 +116,78 @@ impl NamespaceTable { item_impls.push(item_impl); } + Ok(item_impls) + } + + pub fn build_parent_namespace_impl(&self) -> syn::Result> { + if let Some((_, parent_namespace)) = &self.parent_namespace { + let namespace_ident = self.namespace_type.ident.clone(); + let namespace_generics = self.build_namespace_generics()?; + + let namespace_struct_ident = Ident::new( + &format!("__{}Components", namespace_ident), + namespace_ident.span(), + ); + + let namespace_struct: ItemStruct = parse_quote! { + pub struct #namespace_struct_ident; + }; + + let table_type: Type = parse_quote!(__Components__); + + let parent_namespace_ident = &parent_namespace.ident; + + let mut parent_namespace_generics = parent_namespace.generics.clone(); + parent_namespace_generics + .params + .push(parse_quote!(#namespace_struct_ident)); + + let mut generics = self.impl_generics.generics.clone(); + generics.make_where_clause().predicates.push(parse_quote! { + __Component__: #parent_namespace_ident #parent_namespace_generics + }); + + let for_entry = EvaluatedForEntry { + generics: generics.clone(), + table_type: table_type.clone(), + for_key: parse_quote!(__Component__), + for_value: parse_quote!(__Provider__), + mapping_key: parse_quote!(__Component__), + mapping_value: parse_quote!(__Provider__), + namespace_ident, + namespace_generics, + }; + + let evaluated_entry = for_entry.eval_entry(&table_type)?; + + let namespace_trait = self.build_namespace_trait()?; + let item_impl = evaluated_entry.build_namespace_impl(&namespace_trait, &generics)?; + + Ok(Some((namespace_struct, item_impl))) + } else { + Ok(None) + } + } + + pub fn eval(&self) -> syn::Result { + let item_trait = self.build_item_trait()?; + let item_impls = self.build_item_impls()?; + Ok(EvaluatedNamespaceTable { item_impls, item_trait, }) } } + +impl ToTokens for EvaluatedNamespaceTable { + fn to_tokens(&self, tokens: &mut TokenStream) { + if let Some(item_trait) = &self.item_trait { + item_trait.to_tokens(tokens); + } + + for item_impl in &self.item_impls { + item_impl.to_tokens(tokens); + } + } +} diff --git a/crates/cgp-macro-core/src/types/keyword.rs b/crates/cgp-macro-core/src/types/keyword.rs index d676014e..b3993628 100644 --- a/crates/cgp-macro-core/src/types/keyword.rs +++ b/crates/cgp-macro-core/src/types/keyword.rs @@ -12,6 +12,15 @@ pub struct Keyword { pub phantom: PhantomData, } +impl Default for Keyword { + fn default() -> Self { + Self { + span: Span::call_site(), + phantom: PhantomData, + } + } +} + impl Debug for Keyword { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { f.debug_struct("keyword").field("ident", &K::IDENT).finish() diff --git a/crates/cgp-macro-lib/src/entrypoints/cgp_namespace.rs b/crates/cgp-macro-lib/src/entrypoints/cgp_namespace.rs index 0c2623be..29ea7890 100644 --- a/crates/cgp-macro-lib/src/entrypoints/cgp_namespace.rs +++ b/crates/cgp-macro-lib/src/entrypoints/cgp_namespace.rs @@ -1,9 +1,14 @@ +use cgp_macro_core::types::delegate_component::NamespaceTable; use proc_macro2::TokenStream; +use quote::ToTokens; use syn::parse2; use crate::cgp_namespace::{NamespaceSpec, derive_namespace}; pub fn cgp_namespace(body: TokenStream) -> syn::Result { + // let namespace_table: NamespaceTable = parse2(body)?; + // Ok(namespace_table.eval()?.to_token_stream()) + let spec: NamespaceSpec = parse2(body)?; derive_namespace(spec) diff --git a/crates/cgp-tests/src/namespaces/extended.rs b/crates/cgp-tests/src/namespaces/extended.rs index dc681c97..ed00353f 100644 --- a/crates/cgp-tests/src/namespaces/extended.rs +++ b/crates/cgp-tests/src/namespaces/extended.rs @@ -1,6 +1,16 @@ use cgp::core::component::RedirectLookup; use cgp::prelude::*; +// cgp_namespace! { +// new ExtendedNamespace { +// namespace default; + +// // @cgp.core.error >> @app, +// @cgp.core.error => +// @app, +// } +// } + cgp_namespace! { ExtendedNamespace: DefaultNamespace { // @cgp.core.error >> @app, From 02d04b1b71efbecbba3596938377d1e6edb6e137 Mon Sep 17 00:00:00 2001 From: Soares Chen Date: Mon, 25 May 2026 23:47:37 +0200 Subject: [PATCH 70/81] Still fixing namespace inheritance --- .../delegate_component/statement/eval.rs | 4 +-- .../delegate_component/table/namespace.rs | 35 +++++++++++++------ .../src/entrypoints/cgp_namespace.rs | 8 ++--- crates/cgp-tests/src/namespaces/extended.rs | 23 ++++++------ .../namespace_tests/namespace_macro/basic.rs | 4 +-- .../namespace_macro/multi_namespace.rs | 8 ++--- .../namespace_macro/symbol_path.rs | 4 +-- .../namespace_macro/type_path.rs | 4 +-- 8 files changed, 51 insertions(+), 39 deletions(-) diff --git a/crates/cgp-macro-core/src/types/delegate_component/statement/eval.rs b/crates/cgp-macro-core/src/types/delegate_component/statement/eval.rs index bbd5c5f8..01f24cc8 100644 --- a/crates/cgp-macro-core/src/types/delegate_component/statement/eval.rs +++ b/crates/cgp-macro-core/src/types/delegate_component/statement/eval.rs @@ -1,8 +1,6 @@ use syn::{Generics, Ident, Type, parse_quote}; -use crate::types::delegate_component::{ - EvalDelegateEntry, EvaluatedDelegateEntry, -}; +use crate::types::delegate_component::{EvalDelegateEntry, EvaluatedDelegateEntry}; use crate::types::generics::TypeGenerics; pub trait EvalForEntry { diff --git a/crates/cgp-macro-core/src/types/delegate_component/table/namespace.rs b/crates/cgp-macro-core/src/types/delegate_component/table/namespace.rs index d88729e0..4b07a934 100644 --- a/crates/cgp-macro-core/src/types/delegate_component/table/namespace.rs +++ b/crates/cgp-macro-core/src/types/delegate_component/table/namespace.rs @@ -2,7 +2,7 @@ use proc_macro2::TokenStream; use quote::ToTokens; use syn::parse::{Parse, ParseStream}; use syn::token::Colon; -use syn::{Ident, ItemImpl, ItemStruct, ItemTrait, Type, braced, parse_quote}; +use syn::{Generics, Ident, ItemImpl, ItemStruct, ItemTrait, Type, braced, parse_quote}; use crate::traits::PeekKeyword; use crate::types::delegate_component::{ @@ -24,6 +24,7 @@ pub struct NamespaceTable { pub struct EvaluatedNamespaceTable { pub item_impls: Vec, pub item_trait: Option, + pub item_struct: Option, } impl Parse for NamespaceTable { @@ -67,7 +68,7 @@ impl NamespaceTable { let namespace_ident = &self.namespace_type.ident; let mut namespace_generics = self.namespace_type.generics.clone(); - namespace_generics.params.push(parse_quote!(__Components__)); + namespace_generics.params.push(parse_quote!(__Table__)); let item_trait: Option = if self.new.is_some() { let item_trait = parse_quote! { @@ -86,7 +87,7 @@ impl NamespaceTable { pub fn build_namespace_generics(&self) -> syn::Result { let mut namespace_generics = self.namespace_type.generics.clone(); - namespace_generics.params.push(parse_quote!(__Components__)); + namespace_generics.params.push(parse_quote!(__Table__)); Ok(namespace_generics) } @@ -101,10 +102,10 @@ impl NamespaceTable { pub fn build_item_impls(&self) -> syn::Result> { let mut impl_generics = self.impl_generics.clone(); - impl_generics.params.push(parse_quote!(__Components__)); + impl_generics.params.push(parse_quote!(__Table__)); let namespace_trait = self.build_namespace_trait()?; - let table_type: Type = parse_quote!(__Components__); + let table_type: Type = parse_quote!(__Table__); let evaluated_entries = self.entries.eval_entries(&table_type)?; @@ -122,7 +123,9 @@ impl NamespaceTable { pub fn build_parent_namespace_impl(&self) -> syn::Result> { if let Some((_, parent_namespace)) = &self.parent_namespace { let namespace_ident = self.namespace_type.ident.clone(); - let namespace_generics = self.build_namespace_generics()?; + let namespace_generics = self.namespace_type.generics.clone(); + + let table_type: Type = parse_quote!(__Table__); let namespace_struct_ident = Ident::new( &format!("__{}Components", namespace_ident), @@ -133,8 +136,6 @@ impl NamespaceTable { pub struct #namespace_struct_ident; }; - let table_type: Type = parse_quote!(__Components__); - let parent_namespace_ident = &parent_namespace.ident; let mut parent_namespace_generics = parent_namespace.generics.clone(); @@ -143,12 +144,15 @@ impl NamespaceTable { .push(parse_quote!(#namespace_struct_ident)); let mut generics = self.impl_generics.generics.clone(); + + generics.params.push(parse_quote!(__Table__)); + generics.make_where_clause().predicates.push(parse_quote! { __Component__: #parent_namespace_ident #parent_namespace_generics }); let for_entry = EvaluatedForEntry { - generics: generics.clone(), + generics: Generics::default(), table_type: table_type.clone(), for_key: parse_quote!(__Component__), for_value: parse_quote!(__Provider__), @@ -170,18 +174,29 @@ impl NamespaceTable { } pub fn eval(&self) -> syn::Result { + let mut item_struct = None; let item_trait = self.build_item_trait()?; - let item_impls = self.build_item_impls()?; + let mut item_impls = self.build_item_impls()?; + + if let Some((namespace_struct, item_impl)) = self.build_parent_namespace_impl()? { + item_impls.insert(0, item_impl); + item_struct = Some(namespace_struct); + } Ok(EvaluatedNamespaceTable { item_impls, item_trait, + item_struct, }) } } impl ToTokens for EvaluatedNamespaceTable { fn to_tokens(&self, tokens: &mut TokenStream) { + if let Some(item_struct) = &self.item_struct { + item_struct.to_tokens(tokens); + } + if let Some(item_trait) = &self.item_trait { item_trait.to_tokens(tokens); } diff --git a/crates/cgp-macro-lib/src/entrypoints/cgp_namespace.rs b/crates/cgp-macro-lib/src/entrypoints/cgp_namespace.rs index 29ea7890..7b85e15e 100644 --- a/crates/cgp-macro-lib/src/entrypoints/cgp_namespace.rs +++ b/crates/cgp-macro-lib/src/entrypoints/cgp_namespace.rs @@ -6,10 +6,10 @@ use syn::parse2; use crate::cgp_namespace::{NamespaceSpec, derive_namespace}; pub fn cgp_namespace(body: TokenStream) -> syn::Result { - // let namespace_table: NamespaceTable = parse2(body)?; - // Ok(namespace_table.eval()?.to_token_stream()) + let namespace_table: NamespaceTable = parse2(body)?; + Ok(namespace_table.eval()?.to_token_stream()) - let spec: NamespaceSpec = parse2(body)?; + // let spec: NamespaceSpec = parse2(body)?; - derive_namespace(spec) + // derive_namespace(spec) } diff --git a/crates/cgp-tests/src/namespaces/extended.rs b/crates/cgp-tests/src/namespaces/extended.rs index ed00353f..8d68f6a3 100644 --- a/crates/cgp-tests/src/namespaces/extended.rs +++ b/crates/cgp-tests/src/namespaces/extended.rs @@ -1,20 +1,19 @@ use cgp::core::component::RedirectLookup; use cgp::prelude::*; -// cgp_namespace! { -// new ExtendedNamespace { -// namespace default; - -// // @cgp.core.error >> @app, -// @cgp.core.error => -// @app, -// } -// } - cgp_namespace! { - ExtendedNamespace: DefaultNamespace { + new ExtendedNamespace: DefaultNamespace { + // @cgp.core.error >> @app, - @cgp.core.error: + @cgp.core.error => @app, } } + +// cgp_namespace! { +// ExtendedNamespace: DefaultNamespace { +// // @cgp.core.error >> @app, +// @cgp.core.error: +// @app, +// } +// } diff --git a/crates/cgp-tests/tests/namespace_tests/namespace_macro/basic.rs b/crates/cgp-tests/tests/namespace_tests/namespace_macro/basic.rs index 4e4d23b0..ab0aac0c 100644 --- a/crates/cgp-tests/tests/namespace_tests/namespace_macro/basic.rs +++ b/crates/cgp-tests/tests/namespace_tests/namespace_macro/basic.rs @@ -6,8 +6,8 @@ pub trait Foo { } cgp_namespace! { - MyNamespace { - FooProviderComponent: + new MyNamespace { + FooProviderComponent => @MyFooComponent, } } diff --git a/crates/cgp-tests/tests/namespace_tests/namespace_macro/multi_namespace.rs b/crates/cgp-tests/tests/namespace_tests/namespace_macro/multi_namespace.rs index 199bfa0a..4425feb0 100644 --- a/crates/cgp-tests/tests/namespace_tests/namespace_macro/multi_namespace.rs +++ b/crates/cgp-tests/tests/namespace_tests/namespace_macro/multi_namespace.rs @@ -8,15 +8,15 @@ pub trait Foo { } cgp_namespace! { - MyNamespace { - FooProviderComponent: + new MyNamespace { + FooProviderComponent => @MyApp.MyFooComponent, } } cgp_namespace! { - OtherNamespace { - FooProviderComponent: + new OtherNamespace { + FooProviderComponent => @my_app.MyFooComponent, } } diff --git a/crates/cgp-tests/tests/namespace_tests/namespace_macro/symbol_path.rs b/crates/cgp-tests/tests/namespace_tests/namespace_macro/symbol_path.rs index b840bea4..e781932c 100644 --- a/crates/cgp-tests/tests/namespace_tests/namespace_macro/symbol_path.rs +++ b/crates/cgp-tests/tests/namespace_tests/namespace_macro/symbol_path.rs @@ -6,8 +6,8 @@ pub trait Foo { } cgp_namespace! { - MyNamespace { - FooProviderComponent: + new MyNamespace { + FooProviderComponent => @my_app.MyFooComponent, } } diff --git a/crates/cgp-tests/tests/namespace_tests/namespace_macro/type_path.rs b/crates/cgp-tests/tests/namespace_tests/namespace_macro/type_path.rs index bdf477e5..0881b5f1 100644 --- a/crates/cgp-tests/tests/namespace_tests/namespace_macro/type_path.rs +++ b/crates/cgp-tests/tests/namespace_tests/namespace_macro/type_path.rs @@ -8,8 +8,8 @@ pub trait Foo { } cgp_namespace! { - MyNamespace { - FooProviderComponent: + new MyNamespace { + FooProviderComponent => @MyApp.MyFooComponent, } } From 5e36713c81a2682a0659d06899793c81983e503f Mon Sep 17 00:00:00 2001 From: Soares Chen Date: Tue, 26 May 2026 00:00:42 +0200 Subject: [PATCH 71/81] New namespace inheritance is now working --- .../src/types/delegate_component/table/namespace.rs | 5 ++--- crates/cgp-tests/src/namespaces/extended.rs | 13 +------------ 2 files changed, 3 insertions(+), 15 deletions(-) diff --git a/crates/cgp-macro-core/src/types/delegate_component/table/namespace.rs b/crates/cgp-macro-core/src/types/delegate_component/table/namespace.rs index 4b07a934..cc847bac 100644 --- a/crates/cgp-macro-core/src/types/delegate_component/table/namespace.rs +++ b/crates/cgp-macro-core/src/types/delegate_component/table/namespace.rs @@ -123,7 +123,6 @@ impl NamespaceTable { pub fn build_parent_namespace_impl(&self) -> syn::Result> { if let Some((_, parent_namespace)) = &self.parent_namespace { let namespace_ident = self.namespace_type.ident.clone(); - let namespace_generics = self.namespace_type.generics.clone(); let table_type: Type = parse_quote!(__Table__); @@ -158,8 +157,8 @@ impl NamespaceTable { for_value: parse_quote!(__Provider__), mapping_key: parse_quote!(__Component__), mapping_value: parse_quote!(__Provider__), - namespace_ident, - namespace_generics, + namespace_ident: parent_namespace.ident.clone(), + namespace_generics: parent_namespace.generics.clone(), }; let evaluated_entry = for_entry.eval_entry(&table_type)?; diff --git a/crates/cgp-tests/src/namespaces/extended.rs b/crates/cgp-tests/src/namespaces/extended.rs index 8d68f6a3..2e74b25e 100644 --- a/crates/cgp-tests/src/namespaces/extended.rs +++ b/crates/cgp-tests/src/namespaces/extended.rs @@ -1,19 +1,8 @@ -use cgp::core::component::RedirectLookup; -use cgp::prelude::*; +use cgp::prelude::{DefaultNamespace, cgp_namespace}; cgp_namespace! { new ExtendedNamespace: DefaultNamespace { - - // @cgp.core.error >> @app, @cgp.core.error => @app, } } - -// cgp_namespace! { -// ExtendedNamespace: DefaultNamespace { -// // @cgp.core.error >> @app, -// @cgp.core.error: -// @app, -// } -// } From f943d76f6774c3829bba009949522dbc0700ebf9 Mon Sep 17 00:00:00 2001 From: Soares Chen Date: Tue, 26 May 2026 00:01:34 +0200 Subject: [PATCH 72/81] Remove old namespace constructs --- .../cgp-macro-lib/src/cgp_namespace/derive.rs | 134 ------------------ crates/cgp-macro-lib/src/cgp_namespace/mod.rs | 5 - .../cgp-macro-lib/src/cgp_namespace/spec.rs | 53 ------- .../src/entrypoints/cgp_namespace.rs | 6 - crates/cgp-macro-lib/src/lib.rs | 1 - 5 files changed, 199 deletions(-) delete mode 100644 crates/cgp-macro-lib/src/cgp_namespace/derive.rs delete mode 100644 crates/cgp-macro-lib/src/cgp_namespace/mod.rs delete mode 100644 crates/cgp-macro-lib/src/cgp_namespace/spec.rs diff --git a/crates/cgp-macro-lib/src/cgp_namespace/derive.rs b/crates/cgp-macro-lib/src/cgp_namespace/derive.rs deleted file mode 100644 index 1f56895b..00000000 --- a/crates/cgp-macro-lib/src/cgp_namespace/derive.rs +++ /dev/null @@ -1,134 +0,0 @@ -use cgp_macro_core::types::path::PathHeadOrType; -use proc_macro2::TokenStream; -use quote::quote; -use syn::{Ident, ItemImpl, ItemStruct, ItemTrait, parse_quote, parse2}; - -use crate::cgp_namespace::NamespaceSpec; - -pub fn derive_namespace(spec: NamespaceSpec) -> syn::Result { - let mut out = TokenStream::new(); - - let namespace_ident = &spec.namespace_ident; - - let namespace_trait: ItemTrait = parse2(quote! { - pub trait #namespace_ident< __Components__ > { - type Provider; - } - })?; - - out.extend(quote! { - #namespace_trait - }); - - if let Some(parent_namespace_ident) = spec.parent_namespace_ident { - let namespace_struct_ident = Ident::new( - &format!("__{}Components", namespace_ident), - namespace_ident.span(), - ); - - let namespace_struct: ItemStruct = parse2(quote! { - pub struct #namespace_struct_ident; - })?; - - let item_impl: ItemImpl = parse2(quote! { - impl<__Context__, __Components__, __Provider__> - #namespace_ident< __Components__ > - for __Context__ - where - __Context__: #parent_namespace_ident< __Components__, Provider = __Provider__ > - + #parent_namespace_ident< #namespace_struct_ident >, - { - type Provider = __Provider__; - } - })?; - - out.extend(quote! { - #namespace_struct - - #item_impl - }) - } - - for entry in spec.entries.into_iter() { - let value = entry.value; - - match entry.keys { - PathHeadOrType::PathHead(path_head) => { - for (mut generics, path) in path_head.into_paths() { - generics.params.push(parse_quote!(__Components__)); - generics.params.push(parse_quote!(__Wildcard__)); - - let prefix = path.to_prefix(parse_quote!(__Wildcard__)); - - let impl_generics = generics.split_for_impl().0; - let redirect_target = value.clone().to_prefix(parse_quote!(__Wildcard__)); - - let item_impl: ItemImpl = parse2(quote! { - impl #impl_generics - #namespace_ident< __Components__ > - for #prefix - { - type Provider = RedirectLookup< - __Components__, - #redirect_target, - >; - } - })?; - - out.extend(quote! { - #item_impl - }) - } - } - PathHeadOrType::Type(mut generics, ty) => { - generics.params.push(parse_quote!(__Components__)); - let impl_generics = generics.split_for_impl().0; - - let item_impl: ItemImpl = parse2(quote! { - impl #impl_generics - #namespace_ident< __Components__ > - for #ty - { - type Provider = RedirectLookup< - __Components__, - #value, - >; - } - })?; - - out.extend(quote! { - #item_impl - }) - } - } - - // value.append_type(parse_quote!(__Wildcard__)); - - // for path in entry.keys.paths.into_iter() { - // let path_type = path.path_type; - - // let mut generics = path.generics.generics; - // generics.params.push(parse_quote!(__Components__)); - - // let impl_generics = generics.split_for_impl().0; - - // let item_impl: ItemImpl = parse2(quote! { - // impl #impl_generics - // #namespace_ident< __Components__ > - // for #path_type - // { - // type Provider = RedirectLookup< - // __Components__, - // #value, - // >; - // } - // })?; - - // out.extend(quote! { - // #item_impl - // }) - // } - } - - Ok(out) -} diff --git a/crates/cgp-macro-lib/src/cgp_namespace/mod.rs b/crates/cgp-macro-lib/src/cgp_namespace/mod.rs deleted file mode 100644 index 50a77047..00000000 --- a/crates/cgp-macro-lib/src/cgp_namespace/mod.rs +++ /dev/null @@ -1,5 +0,0 @@ -mod derive; -mod spec; - -pub use derive::*; -pub use spec::*; diff --git a/crates/cgp-macro-lib/src/cgp_namespace/spec.rs b/crates/cgp-macro-lib/src/cgp_namespace/spec.rs deleted file mode 100644 index 89152c05..00000000 --- a/crates/cgp-macro-lib/src/cgp_namespace/spec.rs +++ /dev/null @@ -1,53 +0,0 @@ -use cgp_macro_core::types::path::{PathHeadOrType, UniPath}; -use syn::parse::{Parse, ParseStream}; -use syn::punctuated::Punctuated; -use syn::token::{Colon, Comma}; -use syn::{Ident, braced}; - -pub struct NamespaceSpec { - pub namespace_ident: Ident, - pub parent_namespace_ident: Option, - pub entries: Punctuated, -} - -pub struct NamespaceEntry { - pub keys: PathHeadOrType, - pub value: UniPath, -} - -impl Parse for NamespaceSpec { - fn parse(input: ParseStream) -> syn::Result { - let namespace_ident: Ident = input.parse()?; - - let parent_namespace_ident: Option = if input.peek(Colon) { - let _: Colon = input.parse()?; - let ident = input.parse()?; - Some(ident) - } else { - None - }; - - let content; - braced!(content in input); - - let entries = Punctuated::parse_terminated(&content)?; - - Ok(NamespaceSpec { - namespace_ident, - parent_namespace_ident, - entries, - }) - } -} - -impl Parse for NamespaceEntry { - fn parse(input: ParseStream) -> syn::Result { - let keys = input.parse()?; - - let _: Colon = input.parse()?; - - let value = input.parse()?; - - Ok(Self { keys, value }) - } -} diff --git a/crates/cgp-macro-lib/src/entrypoints/cgp_namespace.rs b/crates/cgp-macro-lib/src/entrypoints/cgp_namespace.rs index 7b85e15e..71b9a77f 100644 --- a/crates/cgp-macro-lib/src/entrypoints/cgp_namespace.rs +++ b/crates/cgp-macro-lib/src/entrypoints/cgp_namespace.rs @@ -3,13 +3,7 @@ use proc_macro2::TokenStream; use quote::ToTokens; use syn::parse2; -use crate::cgp_namespace::{NamespaceSpec, derive_namespace}; - pub fn cgp_namespace(body: TokenStream) -> syn::Result { let namespace_table: NamespaceTable = parse2(body)?; Ok(namespace_table.eval()?.to_token_stream()) - - // let spec: NamespaceSpec = parse2(body)?; - - // derive_namespace(spec) } diff --git a/crates/cgp-macro-lib/src/lib.rs b/crates/cgp-macro-lib/src/lib.rs index 23501b7a..2b322b95 100644 --- a/crates/cgp-macro-lib/src/lib.rs +++ b/crates/cgp-macro-lib/src/lib.rs @@ -11,7 +11,6 @@ pub(crate) mod attributes; pub(crate) mod blanket_trait; pub(crate) mod cgp_fn; pub(crate) mod cgp_impl; -pub(crate) mod cgp_namespace; pub(crate) mod check_components; pub(crate) mod delegate_components; pub(crate) mod derive_builder; From b3779286cbd3fda286eae0e30303429584bc22e0 Mon Sep 17 00:00:00 2001 From: Soares Chen Date: Tue, 26 May 2026 00:02:54 +0200 Subject: [PATCH 73/81] Move NamespaceTable --- crates/cgp-macro-core/src/types/delegate_component/table/mod.rs | 2 -- crates/cgp-macro-core/src/types/namespace/mod.rs | 2 ++ .../table/namespace.rs => namespace/table.rs} | 0 crates/cgp-macro-lib/src/entrypoints/cgp_namespace.rs | 2 +- 4 files changed, 3 insertions(+), 3 deletions(-) rename crates/cgp-macro-core/src/types/{delegate_component/table/namespace.rs => namespace/table.rs} (100%) diff --git a/crates/cgp-macro-core/src/types/delegate_component/table/mod.rs b/crates/cgp-macro-core/src/types/delegate_component/table/mod.rs index 297665bc..0e43a88d 100644 --- a/crates/cgp-macro-core/src/types/delegate_component/table/mod.rs +++ b/crates/cgp-macro-core/src/types/delegate_component/table/mod.rs @@ -1,7 +1,5 @@ mod inner; mod main; -mod namespace; pub use inner::*; pub use main::*; -pub use namespace::*; diff --git a/crates/cgp-macro-core/src/types/namespace/mod.rs b/crates/cgp-macro-core/src/types/namespace/mod.rs index d7d9dc2f..164b9b2d 100644 --- a/crates/cgp-macro-core/src/types/namespace/mod.rs +++ b/crates/cgp-macro-core/src/types/namespace/mod.rs @@ -1,3 +1,5 @@ mod ident; +mod table; pub use ident::*; +pub use table::*; diff --git a/crates/cgp-macro-core/src/types/delegate_component/table/namespace.rs b/crates/cgp-macro-core/src/types/namespace/table.rs similarity index 100% rename from crates/cgp-macro-core/src/types/delegate_component/table/namespace.rs rename to crates/cgp-macro-core/src/types/namespace/table.rs diff --git a/crates/cgp-macro-lib/src/entrypoints/cgp_namespace.rs b/crates/cgp-macro-lib/src/entrypoints/cgp_namespace.rs index 71b9a77f..cb8aa32f 100644 --- a/crates/cgp-macro-lib/src/entrypoints/cgp_namespace.rs +++ b/crates/cgp-macro-lib/src/entrypoints/cgp_namespace.rs @@ -1,4 +1,4 @@ -use cgp_macro_core::types::delegate_component::NamespaceTable; +use cgp_macro_core::types::namespace::NamespaceTable; use proc_macro2::TokenStream; use quote::ToTokens; use syn::parse2; From a963114f1a395145bdf0ebf8acaf7497d23c796f Mon Sep 17 00:00:00 2001 From: Soares Chen Date: Tue, 26 May 2026 00:05:22 +0200 Subject: [PATCH 74/81] Only allow inheritance in new namespaces --- crates/cgp-macro-core/src/types/namespace/table.rs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/crates/cgp-macro-core/src/types/namespace/table.rs b/crates/cgp-macro-core/src/types/namespace/table.rs index cc847bac..26077547 100644 --- a/crates/cgp-macro-core/src/types/namespace/table.rs +++ b/crates/cgp-macro-core/src/types/namespace/table.rs @@ -2,7 +2,7 @@ use proc_macro2::TokenStream; use quote::ToTokens; use syn::parse::{Parse, ParseStream}; use syn::token::Colon; -use syn::{Generics, Ident, ItemImpl, ItemStruct, ItemTrait, Type, braced, parse_quote}; +use syn::{Error, Generics, Ident, ItemImpl, ItemStruct, ItemTrait, Type, braced, parse_quote}; use crate::traits::PeekKeyword; use crate::types::delegate_component::{ @@ -122,6 +122,13 @@ impl NamespaceTable { pub fn build_parent_namespace_impl(&self) -> syn::Result> { if let Some((_, parent_namespace)) = &self.parent_namespace { + if self.new.is_none() { + return Err(Error::new( + parent_namespace.ident.span(), + "parent namespace can only be specified with `new` namespaces", + )); + } + let namespace_ident = self.namespace_type.ident.clone(); let table_type: Type = parse_quote!(__Table__); From a621b9578841761a835f166c087787ce7d5a26eb Mon Sep 17 00:00:00 2001 From: Soares Chen Date: Tue, 26 May 2026 21:26:50 +0200 Subject: [PATCH 75/81] Rename `Provider` to `Delegate` in namespace traits --- crates/cgp-component/src/namespaces.rs | 4 ++-- .../src/types/delegate_component/mapping/eval.rs | 2 +- .../src/types/delegate_component/statement/eval.rs | 2 +- .../types/delegate_component/statement/namespace.rs | 9 ++++----- crates/cgp-macro-core/src/types/namespace/table.rs | 13 +++++++------ .../src/derive_component/derive_namespace.rs | 2 +- crates/cgp-tests/src/namespaces/generics.rs | 2 +- .../namespace_macro/default_generics.rs | 9 --------- 8 files changed, 17 insertions(+), 26 deletions(-) diff --git a/crates/cgp-component/src/namespaces.rs b/crates/cgp-component/src/namespaces.rs index 73f21b99..d4e31200 100644 --- a/crates/cgp-component/src/namespaces.rs +++ b/crates/cgp-component/src/namespaces.rs @@ -1,7 +1,7 @@ pub trait DefaultNamespace { - type Provider; + type Delegate; } pub trait DefaultNamespace1 { - type Provider; + type Delegate; } diff --git a/crates/cgp-macro-core/src/types/delegate_component/mapping/eval.rs b/crates/cgp-macro-core/src/types/delegate_component/mapping/eval.rs index 04de4520..70da8f30 100644 --- a/crates/cgp-macro-core/src/types/delegate_component/mapping/eval.rs +++ b/crates/cgp-macro-core/src/types/delegate_component/mapping/eval.rs @@ -88,7 +88,7 @@ impl EvaluatedDelegateEntry { for #key #where_clause { - type Provider = #value; + type Delegate = #value; } }) } diff --git a/crates/cgp-macro-core/src/types/delegate_component/statement/eval.rs b/crates/cgp-macro-core/src/types/delegate_component/statement/eval.rs index 01f24cc8..87aac622 100644 --- a/crates/cgp-macro-core/src/types/delegate_component/statement/eval.rs +++ b/crates/cgp-macro-core/src/types/delegate_component/statement/eval.rs @@ -52,7 +52,7 @@ impl EvalDelegateEntry for EvaluatedForEntry { .push(parse_quote!(#table_type)); namespace_generics.generics.params.push(parse_quote! { - Provider = #mapping_value + Delegate = #mapping_value }); parse_quote!( #namespace_ident #namespace_generics ) diff --git a/crates/cgp-macro-core/src/types/delegate_component/statement/namespace.rs b/crates/cgp-macro-core/src/types/delegate_component/statement/namespace.rs index 7ac18e05..0e3a3a1c 100644 --- a/crates/cgp-macro-core/src/types/delegate_component/statement/namespace.rs +++ b/crates/cgp-macro-core/src/types/delegate_component/statement/namespace.rs @@ -14,7 +14,6 @@ use crate::types::keywords::Namespace; pub struct NamespaceDelegateStatement { pub namespace: Keyword, pub ident: Ident, - pub semi: Semi, } @@ -43,10 +42,10 @@ impl EvalForEntry for NamespaceDelegateStatement { let entry = EvaluatedForEntry { generics: Generics::default(), table_type: table_type.clone(), - for_key: parse_quote!(__Component__), - for_value: parse_quote!(__Provider__), - mapping_key: parse_quote!(__Component__), - mapping_value: parse_quote!(__Provider__), + for_key: parse_quote!(__Key__), + for_value: parse_quote!(__Value__), + mapping_key: parse_quote!(__Key__), + mapping_value: parse_quote!(__Value__), namespace_ident, namespace_generics: TypeGenerics::default(), }; diff --git a/crates/cgp-macro-core/src/types/namespace/table.rs b/crates/cgp-macro-core/src/types/namespace/table.rs index 26077547..1771b9c6 100644 --- a/crates/cgp-macro-core/src/types/namespace/table.rs +++ b/crates/cgp-macro-core/src/types/namespace/table.rs @@ -73,7 +73,7 @@ impl NamespaceTable { let item_trait: Option = if self.new.is_some() { let item_trait = parse_quote! { pub trait #namespace_ident #namespace_generics { - type Provider; + type Delegate; } }; @@ -114,6 +114,7 @@ impl NamespaceTable { for evaluated_entry in evaluated_entries { let item_impl = evaluated_entry.build_namespace_impl(&namespace_trait, &impl_generics)?; + item_impls.push(item_impl); } @@ -154,16 +155,16 @@ impl NamespaceTable { generics.params.push(parse_quote!(__Table__)); generics.make_where_clause().predicates.push(parse_quote! { - __Component__: #parent_namespace_ident #parent_namespace_generics + __Key__: #parent_namespace_ident #parent_namespace_generics }); let for_entry = EvaluatedForEntry { generics: Generics::default(), table_type: table_type.clone(), - for_key: parse_quote!(__Component__), - for_value: parse_quote!(__Provider__), - mapping_key: parse_quote!(__Component__), - mapping_value: parse_quote!(__Provider__), + for_key: parse_quote!(__Key__), + for_value: parse_quote!(__Value__), + mapping_key: parse_quote!(__Key__), + mapping_value: parse_quote!(__Value__), namespace_ident: parent_namespace.ident.clone(), namespace_generics: parent_namespace.generics.clone(), }; diff --git a/crates/cgp-macro-lib/src/derive_component/derive_namespace.rs b/crates/cgp-macro-lib/src/derive_component/derive_namespace.rs index 74095f35..5bcd3559 100644 --- a/crates/cgp-macro-lib/src/derive_component/derive_namespace.rs +++ b/crates/cgp-macro-lib/src/derive_component/derive_namespace.rs @@ -27,7 +27,7 @@ pub fn derive_namespace_impl( let out = quote! { impl<__Components__> #namespace < __Components__ > for #component_name { - type Provider = RedirectLookup< __Components__, #path >; + type Delegate = RedirectLookup< __Components__, #path >; } }; diff --git a/crates/cgp-tests/src/namespaces/generics.rs b/crates/cgp-tests/src/namespaces/generics.rs index 375288d1..cbe1cc57 100644 --- a/crates/cgp-tests/src/namespaces/generics.rs +++ b/crates/cgp-tests/src/namespaces/generics.rs @@ -34,5 +34,5 @@ impl ShowImpl { */ impl DefaultNamespace1 for String { - type Provider = ShowWithDisplay; + type Delegate = ShowWithDisplay; } diff --git a/crates/cgp-tests/tests/namespace_tests/namespace_macro/default_generics.rs b/crates/cgp-tests/tests/namespace_tests/namespace_macro/default_generics.rs index f40559e8..c8523171 100644 --- a/crates/cgp-tests/tests/namespace_tests/namespace_macro/default_generics.rs +++ b/crates/cgp-tests/tests/namespace_tests/namespace_macro/default_generics.rs @@ -23,15 +23,6 @@ delegate_components! { } } -// impl -// DelegateComponent>>> -// for App -// where -// T: DefaultNamespace1, -// { -// type Delegate = T::Provider; -// } - check_components! { App { ShowImplComponent: [ From 3ed9351c0d46b66d858618025c778a8c96416775 Mon Sep 17 00:00:00 2001 From: Soares Chen Date: Tue, 26 May 2026 21:30:27 +0200 Subject: [PATCH 76/81] Always require namespace ident to be specified --- crates/cgp-component/src/lib.rs | 2 +- crates/cgp-component/src/namespaces.rs | 6 +++++- .../src/types/delegate_component/statement/namespace.rs | 8 +------- crates/cgp-tests/src/namespaces/generics.rs | 4 ++-- crates/cgp-tests/tests/namespace_tests/multi_param.rs | 2 +- crates/cgp-tests/tests/namespace_tests/namespace.rs | 2 +- .../namespace_tests/namespace_macro/default_generics.rs | 6 +++--- crates/cgp-tests/tests/namespace_tests/redirect.rs | 2 +- 8 files changed, 15 insertions(+), 17 deletions(-) diff --git a/crates/cgp-component/src/lib.rs b/crates/cgp-component/src/lib.rs index c5d52c0f..9680af2e 100644 --- a/crates/cgp-component/src/lib.rs +++ b/crates/cgp-component/src/lib.rs @@ -11,7 +11,7 @@ mod namespaces; mod providers; mod traits; -pub use namespaces::{DefaultNamespace, DefaultNamespace1}; +pub use namespaces::{DefaultImpls1, DefaultImpls2, DefaultNamespace}; pub use providers::{ RedirectLookup, UseContext, UseDefault, UseDelegate, UseFields, WithContext, WithProvider, }; diff --git a/crates/cgp-component/src/namespaces.rs b/crates/cgp-component/src/namespaces.rs index d4e31200..3daddeb5 100644 --- a/crates/cgp-component/src/namespaces.rs +++ b/crates/cgp-component/src/namespaces.rs @@ -2,6 +2,10 @@ pub trait DefaultNamespace { type Delegate; } -pub trait DefaultNamespace1 { +pub trait DefaultImpls1 { + type Delegate; +} + +pub trait DefaultImpls2 { type Delegate; } diff --git a/crates/cgp-macro-core/src/types/delegate_component/statement/namespace.rs b/crates/cgp-macro-core/src/types/delegate_component/statement/namespace.rs index 0e3a3a1c..64d218fb 100644 --- a/crates/cgp-macro-core/src/types/delegate_component/statement/namespace.rs +++ b/crates/cgp-macro-core/src/types/delegate_component/statement/namespace.rs @@ -33,12 +33,6 @@ impl Parse for NamespaceDelegateStatement { impl EvalForEntry for NamespaceDelegateStatement { fn eval_for(&self, table_type: &Type) -> syn::Result> { - let namespace_ident = if &self.ident == "default" { - Ident::new("DefaultNamespace", self.ident.span()) - } else { - self.ident.clone() - }; - let entry = EvaluatedForEntry { generics: Generics::default(), table_type: table_type.clone(), @@ -46,7 +40,7 @@ impl EvalForEntry for NamespaceDelegateStatement { for_value: parse_quote!(__Value__), mapping_key: parse_quote!(__Key__), mapping_value: parse_quote!(__Value__), - namespace_ident, + namespace_ident: self.ident.clone(), namespace_generics: TypeGenerics::default(), }; diff --git a/crates/cgp-tests/src/namespaces/generics.rs b/crates/cgp-tests/src/namespaces/generics.rs index cbe1cc57..b9ac9a27 100644 --- a/crates/cgp-tests/src/namespaces/generics.rs +++ b/crates/cgp-tests/src/namespaces/generics.rs @@ -1,6 +1,6 @@ use core::fmt::Display; -use cgp::core::component::DefaultNamespace1; +use cgp::core::component::DefaultImpls1; use cgp::prelude::*; #[cgp_component(ShowImpl)] @@ -33,6 +33,6 @@ impl ShowImpl { } */ -impl DefaultNamespace1 for String { +impl DefaultImpls1 for String { type Delegate = ShowWithDisplay; } diff --git a/crates/cgp-tests/tests/namespace_tests/multi_param.rs b/crates/cgp-tests/tests/namespace_tests/multi_param.rs index eaaa7f37..502e2e23 100644 --- a/crates/cgp-tests/tests/namespace_tests/multi_param.rs +++ b/crates/cgp-tests/tests/namespace_tests/multi_param.rs @@ -39,7 +39,7 @@ pub struct AppB; delegate_components! { AppB { - namespace default; + namespace DefaultNamespace; @app.FooProviderComponent.String.u64: DummyFoo, diff --git a/crates/cgp-tests/tests/namespace_tests/namespace.rs b/crates/cgp-tests/tests/namespace_tests/namespace.rs index a16834a5..0742ec6e 100644 --- a/crates/cgp-tests/tests/namespace_tests/namespace.rs +++ b/crates/cgp-tests/tests/namespace_tests/namespace.rs @@ -14,7 +14,7 @@ pub struct App; delegate_components! { App { - namespace default; + namespace DefaultNamespace; @cgp.core.error.ErrorTypeProviderComponent: UseType, diff --git a/crates/cgp-tests/tests/namespace_tests/namespace_macro/default_generics.rs b/crates/cgp-tests/tests/namespace_tests/namespace_macro/default_generics.rs index c8523171..7d1b7d4e 100644 --- a/crates/cgp-tests/tests/namespace_tests/namespace_macro/default_generics.rs +++ b/crates/cgp-tests/tests/namespace_tests/namespace_macro/default_generics.rs @@ -1,4 +1,4 @@ -use cgp::core::component::DefaultNamespace1; +use cgp::core::component::DefaultImpls1; use cgp::prelude::*; use cgp_tests::namespaces::generics::{ShowImplComponent, ShowWithDisplay}; @@ -10,9 +10,9 @@ delegate_components! { // for in DefaultNamespace { // Component: Provider, // } - namespace default; + namespace DefaultNamespace; - for in DefaultNamespace1 { + for in DefaultImpls1 { @test.ShowImplComponent.T: Provider, } diff --git a/crates/cgp-tests/tests/namespace_tests/redirect.rs b/crates/cgp-tests/tests/namespace_tests/redirect.rs index d86dbf45..f47dddd1 100644 --- a/crates/cgp-tests/tests/namespace_tests/redirect.rs +++ b/crates/cgp-tests/tests/namespace_tests/redirect.rs @@ -19,7 +19,7 @@ pub struct App; delegate_components! { App { - namespace default; + namespace DefaultNamespace; // @bar: TestProvider, From 21315984ad5d0b2b479442dee489bb33c90ea5f8 Mon Sep 17 00:00:00 2001 From: Soares Chen Date: Tue, 26 May 2026 22:20:34 +0200 Subject: [PATCH 77/81] Implement InheritNamespaceStatement --- .../delegate_component/statement/eval.rs | 10 ++++-- .../delegate_component/statement/for_loop.rs | 9 ++--- .../delegate_component/statement/namespace.rs | 11 ++++-- .../src/types/namespace/inherit.rs | 35 +++++++++++++++++++ .../cgp-macro-core/src/types/namespace/mod.rs | 2 ++ 5 files changed, 58 insertions(+), 9 deletions(-) create mode 100644 crates/cgp-macro-core/src/types/namespace/inherit.rs diff --git a/crates/cgp-macro-core/src/types/delegate_component/statement/eval.rs b/crates/cgp-macro-core/src/types/delegate_component/statement/eval.rs index 87aac622..8a47c5b5 100644 --- a/crates/cgp-macro-core/src/types/delegate_component/statement/eval.rs +++ b/crates/cgp-macro-core/src/types/delegate_component/statement/eval.rs @@ -3,8 +3,12 @@ use syn::{Generics, Ident, Type, parse_quote}; use crate::types::delegate_component::{EvalDelegateEntry, EvaluatedDelegateEntry}; use crate::types::generics::TypeGenerics; +pub trait EvalForEntries { + fn eval_for_entries(&self, table_type: &Type) -> syn::Result>; +} + pub trait EvalForEntry { - fn eval_for(&self, table_type: &Type) -> syn::Result>; + fn eval_for_entry(&self, table_type: &Type) -> syn::Result; } pub struct EvaluatedForEntry { @@ -23,11 +27,11 @@ pub fn eval_delegate_entries_via_for( table_type: &Type, ) -> syn::Result> where - Entry: EvalForEntry, + Entry: EvalForEntries, { let mut entries = Vec::new(); - let for_entries = entry.eval_for(table_type)?; + let for_entries = entry.eval_for_entries(table_type)?; for for_entry in for_entries { entries.push(for_entry.eval_entry(table_type)?); } diff --git a/crates/cgp-macro-core/src/types/delegate_component/statement/for_loop.rs b/crates/cgp-macro-core/src/types/delegate_component/statement/for_loop.rs index bb8bb22e..511c633a 100644 --- a/crates/cgp-macro-core/src/types/delegate_component/statement/for_loop.rs +++ b/crates/cgp-macro-core/src/types/delegate_component/statement/for_loop.rs @@ -4,8 +4,9 @@ use syn::token::{Comma, For, Gt, In, Lt}; use syn::{Ident, Type, WhereClause, braced}; use crate::types::delegate_component::{ - EvalDelegateEntries, EvalDelegateKey, EvalDelegateValue, EvalForEntry, EvaluatedDelegateEntry, - EvaluatedForEntry, NormalDelegateMapping, eval_delegate_entries_via_for, + EvalDelegateEntries, EvalDelegateKey, EvalDelegateValue, EvalForEntries, + EvaluatedDelegateEntry, EvaluatedForEntry, NormalDelegateMapping, + eval_delegate_entries_via_for, }; use crate::types::ident_type::IdentType; @@ -56,8 +57,8 @@ impl Parse for ForDelegateStatement { } } -impl EvalForEntry for ForDelegateStatement { - fn eval_for(&self, table_type: &Type) -> syn::Result> { +impl EvalForEntries for ForDelegateStatement { + fn eval_for_entries(&self, table_type: &Type) -> syn::Result> { let mut entries = Vec::new(); for mapping in &self.mappings { diff --git a/crates/cgp-macro-core/src/types/delegate_component/statement/namespace.rs b/crates/cgp-macro-core/src/types/delegate_component/statement/namespace.rs index 64d218fb..81074ae3 100644 --- a/crates/cgp-macro-core/src/types/delegate_component/statement/namespace.rs +++ b/crates/cgp-macro-core/src/types/delegate_component/statement/namespace.rs @@ -3,7 +3,7 @@ use syn::token::Semi; use syn::{Generics, Ident, Type, parse_quote}; use crate::types::delegate_component::{ - EvalDelegateEntries, EvalForEntry, EvaluatedDelegateEntry, EvaluatedForEntry, + EvalDelegateEntries, EvalForEntries, EvalForEntry, EvaluatedDelegateEntry, EvaluatedForEntry, eval_delegate_entries_via_for, }; use crate::types::generics::TypeGenerics; @@ -32,7 +32,7 @@ impl Parse for NamespaceDelegateStatement { } impl EvalForEntry for NamespaceDelegateStatement { - fn eval_for(&self, table_type: &Type) -> syn::Result> { + fn eval_for_entry(&self, table_type: &Type) -> syn::Result { let entry = EvaluatedForEntry { generics: Generics::default(), table_type: table_type.clone(), @@ -44,6 +44,13 @@ impl EvalForEntry for NamespaceDelegateStatement { namespace_generics: TypeGenerics::default(), }; + Ok(entry) + } +} + +impl EvalForEntries for NamespaceDelegateStatement { + fn eval_for_entries(&self, table_type: &Type) -> syn::Result> { + let entry = self.eval_for_entry(table_type)?; Ok(vec![entry]) } } diff --git a/crates/cgp-macro-core/src/types/namespace/inherit.rs b/crates/cgp-macro-core/src/types/namespace/inherit.rs new file mode 100644 index 00000000..7435b00f --- /dev/null +++ b/crates/cgp-macro-core/src/types/namespace/inherit.rs @@ -0,0 +1,35 @@ +use syn::{Generics, Ident, Type, parse_quote}; + +use crate::types::delegate_component::{EvalForEntry, EvaluatedForEntry}; +use crate::types::generics::TypeGenerics; + +#[derive(Debug, Clone)] +pub struct InheritNamespaceStatement { + pub ident: Ident, + pub type_generics: TypeGenerics, +} + +impl EvalForEntry for InheritNamespaceStatement { + fn eval_for_entry(&self, table_type: &Type) -> syn::Result { + let namespace_ident = &self.ident; + let namespace_generics = &self.type_generics; + + let mut generics = Generics::default(); + generics.make_where_clause().predicates.push(parse_quote! { + __Key__: #namespace_ident #namespace_generics + }); + + let for_entry = EvaluatedForEntry { + generics, + table_type: table_type.clone(), + for_key: parse_quote!(__Key__), + for_value: parse_quote!(__Value__), + mapping_key: parse_quote!(__Key__), + mapping_value: parse_quote!(__Value__), + namespace_ident: self.ident.clone(), + namespace_generics: self.type_generics.clone(), + }; + + Ok(for_entry) + } +} diff --git a/crates/cgp-macro-core/src/types/namespace/mod.rs b/crates/cgp-macro-core/src/types/namespace/mod.rs index 164b9b2d..6a63e4d7 100644 --- a/crates/cgp-macro-core/src/types/namespace/mod.rs +++ b/crates/cgp-macro-core/src/types/namespace/mod.rs @@ -1,5 +1,7 @@ mod ident; +mod inherit; mod table; pub use ident::*; +pub use inherit::*; pub use table::*; From 641bcc7b56e399aeec53f746ce8d0403b19ff75a Mon Sep 17 00:00:00 2001 From: Soares Chen Date: Tue, 26 May 2026 22:32:46 +0200 Subject: [PATCH 78/81] Use InheritNamespaceStatement to derive namespace impl --- .../src/types/namespace/inherit.rs | 15 ++++++-- .../src/types/namespace/table.rs | 38 ++++++------------- 2 files changed, 23 insertions(+), 30 deletions(-) diff --git a/crates/cgp-macro-core/src/types/namespace/inherit.rs b/crates/cgp-macro-core/src/types/namespace/inherit.rs index 7435b00f..7852a286 100644 --- a/crates/cgp-macro-core/src/types/namespace/inherit.rs +++ b/crates/cgp-macro-core/src/types/namespace/inherit.rs @@ -7,16 +7,23 @@ use crate::types::generics::TypeGenerics; pub struct InheritNamespaceStatement { pub ident: Ident, pub type_generics: TypeGenerics, + pub local_table_ident: Ident, } impl EvalForEntry for InheritNamespaceStatement { fn eval_for_entry(&self, table_type: &Type) -> syn::Result { - let namespace_ident = &self.ident; - let namespace_generics = &self.type_generics; + let namespace_ident = self.ident.clone(); + let local_table_ident = &self.local_table_ident; + + let mut namespace_where_generics = self.type_generics.clone(); + + namespace_where_generics + .params + .push(parse_quote!(#local_table_ident)); let mut generics = Generics::default(); generics.make_where_clause().predicates.push(parse_quote! { - __Key__: #namespace_ident #namespace_generics + __Key__: #namespace_ident #namespace_where_generics }); let for_entry = EvaluatedForEntry { @@ -26,7 +33,7 @@ impl EvalForEntry for InheritNamespaceStatement { for_value: parse_quote!(__Value__), mapping_key: parse_quote!(__Key__), mapping_value: parse_quote!(__Value__), - namespace_ident: self.ident.clone(), + namespace_ident, namespace_generics: self.type_generics.clone(), }; diff --git a/crates/cgp-macro-core/src/types/namespace/table.rs b/crates/cgp-macro-core/src/types/namespace/table.rs index 1771b9c6..f0165546 100644 --- a/crates/cgp-macro-core/src/types/namespace/table.rs +++ b/crates/cgp-macro-core/src/types/namespace/table.rs @@ -2,16 +2,17 @@ use proc_macro2::TokenStream; use quote::ToTokens; use syn::parse::{Parse, ParseStream}; use syn::token::Colon; -use syn::{Error, Generics, Ident, ItemImpl, ItemStruct, ItemTrait, Type, braced, parse_quote}; +use syn::{Error, Ident, ItemImpl, ItemStruct, ItemTrait, Type, braced, parse_quote}; use crate::traits::PeekKeyword; use crate::types::delegate_component::{ - DelegateEntries, EvalDelegateEntries, EvalDelegateEntry, EvaluatedForEntry, + DelegateEntries, EvalDelegateEntries, EvalDelegateEntry, EvalForEntry, }; use crate::types::generics::{ImplGenerics, TypeGenerics}; use crate::types::ident_type::IdentType; use crate::types::keyword::Keyword; use crate::types::keywords::New; +use crate::types::namespace::InheritNamespaceStatement; pub struct NamespaceTable { pub impl_generics: ImplGenerics, @@ -143,35 +144,20 @@ impl NamespaceTable { pub struct #namespace_struct_ident; }; - let parent_namespace_ident = &parent_namespace.ident; + let for_entry = InheritNamespaceStatement { + ident: parent_namespace.ident.clone(), + type_generics: parent_namespace.generics.clone(), + local_table_ident: namespace_struct_ident, + } + .eval_for_entry(&table_type)?; - let mut parent_namespace_generics = parent_namespace.generics.clone(); - parent_namespace_generics - .params - .push(parse_quote!(#namespace_struct_ident)); + let evaluated_entry = for_entry.eval_entry(&table_type)?; - let mut generics = self.impl_generics.generics.clone(); + let namespace_trait = self.build_namespace_trait()?; + let mut generics = self.impl_generics.generics.clone(); generics.params.push(parse_quote!(__Table__)); - generics.make_where_clause().predicates.push(parse_quote! { - __Key__: #parent_namespace_ident #parent_namespace_generics - }); - - let for_entry = EvaluatedForEntry { - generics: Generics::default(), - table_type: table_type.clone(), - for_key: parse_quote!(__Key__), - for_value: parse_quote!(__Value__), - mapping_key: parse_quote!(__Key__), - mapping_value: parse_quote!(__Value__), - namespace_ident: parent_namespace.ident.clone(), - namespace_generics: parent_namespace.generics.clone(), - }; - - let evaluated_entry = for_entry.eval_entry(&table_type)?; - - let namespace_trait = self.build_namespace_trait()?; let item_impl = evaluated_entry.build_namespace_impl(&namespace_trait, &generics)?; Ok(Some((namespace_struct, item_impl))) From 22844903920d83ed75a7ec9d89f1bd4f5099042c Mon Sep 17 00:00:00 2001 From: Soares Chen Date: Tue, 26 May 2026 22:43:57 +0200 Subject: [PATCH 79/81] Slight refactoring --- .../src/types/namespace/eval.rs | 25 ++++ .../cgp-macro-core/src/types/namespace/mod.rs | 2 + .../src/types/namespace/table.rs | 117 +++++++----------- 3 files changed, 69 insertions(+), 75 deletions(-) create mode 100644 crates/cgp-macro-core/src/types/namespace/eval.rs diff --git a/crates/cgp-macro-core/src/types/namespace/eval.rs b/crates/cgp-macro-core/src/types/namespace/eval.rs new file mode 100644 index 00000000..5fa14135 --- /dev/null +++ b/crates/cgp-macro-core/src/types/namespace/eval.rs @@ -0,0 +1,25 @@ +use proc_macro2::TokenStream; +use quote::ToTokens; +use syn::{ItemImpl, ItemStruct, ItemTrait}; + +pub struct EvaluatedNamespaceTable { + pub item_impls: Vec, + pub item_trait: Option, + pub item_struct: Option, +} + +impl ToTokens for EvaluatedNamespaceTable { + fn to_tokens(&self, tokens: &mut TokenStream) { + if let Some(item_struct) = &self.item_struct { + item_struct.to_tokens(tokens); + } + + if let Some(item_trait) = &self.item_trait { + item_trait.to_tokens(tokens); + } + + for item_impl in &self.item_impls { + item_impl.to_tokens(tokens); + } + } +} diff --git a/crates/cgp-macro-core/src/types/namespace/mod.rs b/crates/cgp-macro-core/src/types/namespace/mod.rs index 6a63e4d7..d8f487b1 100644 --- a/crates/cgp-macro-core/src/types/namespace/mod.rs +++ b/crates/cgp-macro-core/src/types/namespace/mod.rs @@ -1,7 +1,9 @@ +mod eval; mod ident; mod inherit; mod table; +pub use eval::*; pub use ident::*; pub use inherit::*; pub use table::*; diff --git a/crates/cgp-macro-core/src/types/namespace/table.rs b/crates/cgp-macro-core/src/types/namespace/table.rs index f0165546..d84b9400 100644 --- a/crates/cgp-macro-core/src/types/namespace/table.rs +++ b/crates/cgp-macro-core/src/types/namespace/table.rs @@ -1,5 +1,3 @@ -use proc_macro2::TokenStream; -use quote::ToTokens; use syn::parse::{Parse, ParseStream}; use syn::token::Colon; use syn::{Error, Ident, ItemImpl, ItemStruct, ItemTrait, Type, braced, parse_quote}; @@ -8,11 +6,11 @@ use crate::traits::PeekKeyword; use crate::types::delegate_component::{ DelegateEntries, EvalDelegateEntries, EvalDelegateEntry, EvalForEntry, }; -use crate::types::generics::{ImplGenerics, TypeGenerics}; +use crate::types::generics::ImplGenerics; use crate::types::ident_type::IdentType; use crate::types::keyword::Keyword; use crate::types::keywords::New; -use crate::types::namespace::InheritNamespaceStatement; +use crate::types::namespace::{EvaluatedNamespaceTable, InheritNamespaceStatement}; pub struct NamespaceTable { pub impl_generics: ImplGenerics, @@ -22,12 +20,6 @@ pub struct NamespaceTable { pub entries: DelegateEntries, } -pub struct EvaluatedNamespaceTable { - pub item_impls: Vec, - pub item_trait: Option, - pub item_struct: Option, -} - impl Parse for NamespaceTable { fn parse(input: ParseStream) -> syn::Result { let impl_generics = input.parse()?; @@ -65,15 +57,21 @@ impl Parse for NamespaceTable { } impl NamespaceTable { - pub fn build_item_trait(&self) -> syn::Result> { + pub fn build_namespace_trait(&self) -> syn::Result { let namespace_ident = &self.namespace_type.ident; - let mut namespace_generics = self.namespace_type.generics.clone(); namespace_generics.params.push(parse_quote!(__Table__)); + let namespace_trait: Type = parse_quote!( #namespace_ident #namespace_generics ); + Ok(namespace_trait) + } + + pub fn build_item_trait(&self) -> syn::Result> { + let namespace_trait = self.build_namespace_trait()?; + let item_trait: Option = if self.new.is_some() { let item_trait = parse_quote! { - pub trait #namespace_ident #namespace_generics { + pub trait #namespace_trait { type Delegate; } }; @@ -86,21 +84,6 @@ impl NamespaceTable { Ok(item_trait) } - pub fn build_namespace_generics(&self) -> syn::Result { - let mut namespace_generics = self.namespace_type.generics.clone(); - namespace_generics.params.push(parse_quote!(__Table__)); - - Ok(namespace_generics) - } - - pub fn build_namespace_trait(&self) -> syn::Result { - let namespace_ident = &self.namespace_type.ident; - let namespace_generics = self.build_namespace_generics()?; - - let namespace_trait: Type = parse_quote!( #namespace_ident #namespace_generics ); - Ok(namespace_trait) - } - pub fn build_item_impls(&self) -> syn::Result> { let mut impl_generics = self.impl_generics.clone(); impl_generics.params.push(parse_quote!(__Table__)); @@ -123,47 +106,47 @@ impl NamespaceTable { } pub fn build_parent_namespace_impl(&self) -> syn::Result> { - if let Some((_, parent_namespace)) = &self.parent_namespace { - if self.new.is_none() { - return Err(Error::new( - parent_namespace.ident.span(), - "parent namespace can only be specified with `new` namespaces", - )); - } + let Some((_, parent_namespace)) = &self.parent_namespace else { + return Ok(None); + }; - let namespace_ident = self.namespace_type.ident.clone(); + if self.new.is_none() { + return Err(Error::new( + parent_namespace.ident.span(), + "parent namespace can only be specified with `new` namespaces", + )); + } - let table_type: Type = parse_quote!(__Table__); + let namespace_ident = self.namespace_type.ident.clone(); - let namespace_struct_ident = Ident::new( - &format!("__{}Components", namespace_ident), - namespace_ident.span(), - ); + let table_type: Type = parse_quote!(__Table__); - let namespace_struct: ItemStruct = parse_quote! { - pub struct #namespace_struct_ident; - }; + let namespace_struct_ident = Ident::new( + &format!("__{}Components", namespace_ident), + namespace_ident.span(), + ); - let for_entry = InheritNamespaceStatement { - ident: parent_namespace.ident.clone(), - type_generics: parent_namespace.generics.clone(), - local_table_ident: namespace_struct_ident, - } - .eval_for_entry(&table_type)?; + let namespace_struct: ItemStruct = parse_quote! { + pub struct #namespace_struct_ident; + }; - let evaluated_entry = for_entry.eval_entry(&table_type)?; + let for_entry = InheritNamespaceStatement { + ident: parent_namespace.ident.clone(), + type_generics: parent_namespace.generics.clone(), + local_table_ident: namespace_struct_ident, + } + .eval_for_entry(&table_type)?; - let namespace_trait = self.build_namespace_trait()?; + let evaluated_entry = for_entry.eval_entry(&table_type)?; - let mut generics = self.impl_generics.generics.clone(); - generics.params.push(parse_quote!(__Table__)); + let namespace_trait = self.build_namespace_trait()?; - let item_impl = evaluated_entry.build_namespace_impl(&namespace_trait, &generics)?; + let mut generics = self.impl_generics.generics.clone(); + generics.params.push(parse_quote!(#table_type)); - Ok(Some((namespace_struct, item_impl))) - } else { - Ok(None) - } + let item_impl = evaluated_entry.build_namespace_impl(&namespace_trait, &generics)?; + + Ok(Some((namespace_struct, item_impl))) } pub fn eval(&self) -> syn::Result { @@ -183,19 +166,3 @@ impl NamespaceTable { }) } } - -impl ToTokens for EvaluatedNamespaceTable { - fn to_tokens(&self, tokens: &mut TokenStream) { - if let Some(item_struct) = &self.item_struct { - item_struct.to_tokens(tokens); - } - - if let Some(item_trait) = &self.item_trait { - item_trait.to_tokens(tokens); - } - - for item_impl in &self.item_impls { - item_impl.to_tokens(tokens); - } - } -} From f9cf4d319783f32e95ba880d82a0d3ab17d74a80 Mon Sep 17 00:00:00 2001 From: Soares Chen Date: Tue, 26 May 2026 22:45:18 +0200 Subject: [PATCH 80/81] Fix clippy --- crates/cgp-macro-core/src/types/keyword.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/cgp-macro-core/src/types/keyword.rs b/crates/cgp-macro-core/src/types/keyword.rs index b3993628..812e3467 100644 --- a/crates/cgp-macro-core/src/types/keyword.rs +++ b/crates/cgp-macro-core/src/types/keyword.rs @@ -30,7 +30,7 @@ impl Debug for Keyword { impl Clone for Keyword { fn clone(&self) -> Self { Self { - span: self.span.clone(), + span: self.span, phantom: PhantomData, } } From 4eb1e7f3fadfdc05d8296019d26665a29186802d Mon Sep 17 00:00:00 2001 From: Soares Chen Date: Tue, 26 May 2026 22:48:21 +0200 Subject: [PATCH 81/81] Fix clippy --- .../src/types/delegate_component/statement/combined.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/cgp-macro-core/src/types/delegate_component/statement/combined.rs b/crates/cgp-macro-core/src/types/delegate_component/statement/combined.rs index a1ea5935..53c40386 100644 --- a/crates/cgp-macro-core/src/types/delegate_component/statement/combined.rs +++ b/crates/cgp-macro-core/src/types/delegate_component/statement/combined.rs @@ -13,7 +13,7 @@ use crate::types::keywords::{Namespace, Open}; pub enum DelegateStatement { Namespace(NamespaceDelegateStatement), Open(OpenDelegateStatement), - For(ForDelegateStatement), + For(Box), } impl DelegateStatement {