#[macro_export] macro_rules! Build { { $(#[$($attr:tt)*])* $vis:vis struct $name:ident {$( $fvis:vis $field:ident: $type:ty ),* $(,)?} } => { #[allow(non_upper_case_globals, non_snake_case, non_camel_case_types)] const _: () = { // add a module here to seal fields. impl<'lt, 'ctx, M: 'ctx, E: effectful::environment::Environment> $crate::Build<'lt, 'ctx, M, E> for $name where effectful::bound::Dynamic<$name>: effectful::bound::DynBind, $($type: $crate::Build<'lt, 'ctx, M, E>,)* $(effectful::bound::Dynamic<$type>: effectful::bound::DynBind,)* $crate::build::builders::core::r#struct::StructBuilder<'lt, 'ctx, __Info, M, E>: $crate::Builder<'lt, 'ctx, E, Value = Self> { type Builder = $crate::build::builders::core::r#struct::StructBuilder<'lt, 'ctx, __Info, M, E>; } #[derive(SendSync)] $vis struct Builders<'lt, 'ctx, M: 'ctx, E: effectful::environment::Environment> where $($type: $crate::Build<'lt, 'ctx, M, E>),* { $($field: <$type as $crate::Build<'lt, 'ctx, M, E>>::Builder),* } #[derive(Copy, Clone, Debug, SendSync)] $vis enum Field { $($field),* } mod field_index { enum __Fields { $($field),* } $(pub const $field: usize = __Fields::$field as usize;)* } #[derive(SendSync)] $vis enum Error<'lt, 'ctx, M: 'ctx, E: effectful::environment::Environment> where $($type: $crate::Build<'lt, 'ctx, M, E>),* { $($field(<<$type as $crate::Build<'lt, 'ctx, M, E>>::Builder as $crate::build::BuilderTypes>::Error)),* } impl ::core::fmt::Display for Field { fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { f.write_str(match self { $(Field::$field => stringify!($field)),* }) } } impl<'lt, 'ctx, M: 'ctx, E: effectful::environment::Environment> ::core::fmt::Debug for Error<'lt, 'ctx, M, E> where $($type: $crate::Build<'lt, 'ctx, M, E>),* { fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { f.write_str(match self { $(Error::$field(_) => stringify!($field)),* }) } } impl<'lt, 'ctx, M: 'ctx, E: effectful::environment::Environment> ::core::fmt::Display for Error<'lt, 'ctx, M, E> where $($type: $crate::Build<'lt, 'ctx, M, E>),* { fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { f.write_str(match self { $(Error::$field(_) => stringify!($field)),* }) } } #[derive(SendSync)] $vis struct __Info; impl<'lt, 'ctx, M: 'ctx, E: effectful::environment::Environment> $crate::build::builders::core::r#struct::StructTypeInfo<'lt, 'ctx, M, E> for __Info where effectful::bound::Dynamic<$name>: effectful::bound::DynBind, $($type: $crate::Build<'lt, 'ctx, M, E>,)* $(effectful::bound::Dynamic<$type>: effectful::bound::DynBind),* { type Builders = Builders<'lt, 'ctx, M, E>; type FieldMarker = Field; type T = $name; type Error = Error<'lt, 'ctx, M, E>; type Seed = ($(<<$type as $crate::Build<'lt, 'ctx, M, E>>::Builder as $crate::build::BuilderTypes>::Seed),*); type ValueT = $crate::any::OwnedStatic>; const FIELD_COUNT: usize = { [$(stringify!($field)),*].len() }; #[inline(always)] fn new_builders<'a>(seed: Self::Seed) -> effectful::effective::Canonical<'a, Self::Builders, E> { let ($($field),*) = seed; use effectful::effective::Effective; use effectful::join; ::effectful::join!( $(#[capture($field)] || <<$type as $crate::Build<'lt, 'ctx, M, E>>::Builder as $crate::Builder::>::from_seed($field),)* ).map((), |_, ($($field,)*)| { Builders { $($field),* } }) .cast() } fn from_builders<'a>(builders: Self::Builders) -> effectful::effective::Canonical<'a, Result, Self::Error>, E> { use $crate::Builder; use effectful::effective::Effective; use $crate::build::BuilderTypes; use effectful::try_join; let Builders { $($field),* } = builders; ::effectful::try_join!( $(#[capture($field)] || $field.build().map((), |_, x| x.map(|x| effectful::bound::Dynamic(<<$type as Build<'lt, 'ctx, M, E>>::Builder as BuilderTypes>::unwrap_output(x))).map_err(Error::$field)),)* ).map((), |_, result| match result { Ok(($(effectful::bound::Dynamic($field),)*)) => Ok(effectful::bound::Dynamic($name { $($field),* })), Err(err) => Err(err) }) .cast() } fn as_visitor<'a>( marker: Self::FieldMarker, builders: &'a mut Self::Builders, ) -> $crate::protocol::DynVisitor<'a, 'lt, 'ctx, E> { use $crate::protocol::AsVisitor; match marker { $(Field::$field => builders.$field.as_visitor()),* } } fn marker_from_index(index: usize) -> Option { match index { $(field_index::$field => Some(Field::$field),)* _ => None } } fn marker_from_name(name: &str) -> Option { match name { $(stringify!($field) => Some(Field::$field),)* _ => None } } fn from_value(value: Self::ValueT) -> Self::T { value.0.0 } } }; }; { $(#[$($attr:tt)*])* $vis:vis enum $name:ident {$( $variant:ident($value:ty) ),* $(,)?} } => { #[allow(non_upper_case_globals, non_snake_case, non_camel_case_types)] const _: () = { // add a module here to seal fields. impl<'ctx, M: 'ctx, E: effectful::environment::Environment> $crate::Build<'ctx, M, E> for $name where effectful::bound::Dynamic<$name>: effectful::bound::DynBind, $($value: $crate::Build<'ctx, M, E>,)* $(<<$value as Build<'ctx, M, E>>::Builder as BuilderTypes>::Seed: Default,)* $crate::build::builders::core::r#enum::EnumBuilder<'ctx, __Info, M, E>: $crate::Builder<'ctx, E, Value = Self> { type Builder = $crate::build::builders::core::r#enum::EnumBuilder<'ctx, __Info, M, E>; } #[derive(SendSync)] $vis struct __Info; #[derive(SendSync)] $vis enum __Builders<'ctx, M, E: effectful::environment::Environment> where $($value: $crate::Build<'ctx, M, E>),* { $($variant(<$value as $crate::Build<'ctx, M, E>>::Builder)),* } #[derive(Copy, Clone, SendSync)] $vis enum __Marker { $($variant),* } impl ::core::fmt::Display for __Marker { fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { f.write_str(match self { $(Self::$variant => stringify!($variant)),* }) } } mod variant_index { enum __Variants { $($variant),* } $(pub const $variant: u32 = __Variants::$variant as u32;)* } #[derive(SendSync)] $vis struct __ErrorBuilder<'ctx, M, E: Environment> where $($value: $crate::Build<'ctx, M, E>),* { $($variant: Option<<<$value as $crate::Build<'ctx, M, E>>::Builder as BuilderTypes>::Error>),* } #[derive(SendSync)] $vis enum __Error<'ctx, M, E: Environment> where $($value: $crate::Build<'ctx, M, E>),* { __Guess { $($variant: <<$value as $crate::Build<'ctx, M, E>>::Builder as BuilderTypes>::Error),* }, $($variant(<<$value as $crate::Build<'ctx, M, E>>::Builder as BuilderTypes>::Error)),* } impl<'ctx, M, E: Environment> ::core::fmt::Display for __Error<'ctx, M, E> where $($value: $crate::Build<'ctx, M, E>),* { fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { match self { Self::__Guess { $($variant),* } => { $(writeln!(f, "{}: {}", stringify!($variant), $variant)?;)* Ok(()) } $(Self::$variant(value) => write!(f, "{}: {}", stringify!($variant), value)),* } } } impl<'ctx, M, E: Environment> ::core::fmt::Debug for __Error<'ctx, M, E> where $($value: $crate::Build<'ctx, M, E>),* { fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { match self { Self::__Guess { $($variant),* } => { $(writeln!(f, "{}: {:?}", stringify!($variant), $variant)?;)* Ok(()) } $(Self::$variant(value) => write!(f, "{}: {:?}", stringify!($variant), value)),* } } } impl<'ctx, M: 'ctx, E: effectful::environment::Environment> $crate::build::builders::core::r#enum::EnumBuildInfo<'ctx, M, E> for __Info where effectful::bound::Dynamic<$name>: effectful::bound::DynBind, $($value: $crate::Build<'ctx, M, E>,)* $(<<$value as Build<'ctx, M, E>>::Builder as BuilderTypes>::Seed: Default),* { type Builders = __Builders<'ctx, M, E>; type Seed = (); type Error = __Error<'ctx, M, E>; type ValueT = $crate::any::OwnedStatic<$name>; type T = $name; type VariantMarker = __Marker; fn new_builder<'a>( seed: Self::Seed, variant: Self::VariantMarker, ) -> Canonical<'a, Self::Builders, E> { match variant { $(__Marker::$variant => { Builder::::from_seed(Default::default()).map((), |_, builder| __Builders::$variant(builder)).cast() })* } } fn finish_builder<'a>( builder: Self::Builders, ) -> Canonical<'a, Result, Self::Error>, E> { match builder { $(__Builders::$variant(builder) => builder.build().map((), |_, value| value.map(|x| effectful::bound::Dynamic($name::$variant(<<$value as Build<'ctx, M, E>>::Builder as BuilderTypes>::unwrap_output(x)))).map_err(__Error::$variant)).cast()),* } } fn from_value<'a>(value: $crate::any::type_name::Lowered<'a, 'ctx, Self::ValueT, E>) -> Self::T { value.0 } fn as_visitor<'a>(builder: &'a mut Self::Builders) -> DynVisitor<'a, 'ctx, E> { match builder { $(__Builders::$variant(builder) => builder.as_visitor()),* } } fn marker_from_name(name: &str) -> Option { match name { $(stringify!($variant) => Some(__Marker::$variant),)* _ => None } } fn marker_from_discriminant(discriminant: u32) -> Option { match discriminant { $(variant_index::$variant => Some(__Marker::$variant),)* _ => None } } fn guess_variant<'a>( seed: Self::Seed, scope: DynRecoverableScope<'a, 'ctx, E>, ) -> Canonical<'a, Result, Self::Error>, E> { use effectful::effective::Effective; use effectful::short::ResultErrorExt; E::value((scope, Err(__ErrorBuilder:: { A: None, B: None }))) $(.or_else_update((), |_, scope, result| { let mut error = result.into_error(); <<$value as Build>::Builder as Builder<_>>::from_seed(Default::default()) .map(scope, |scope, builder| (scope, builder)) .update_map((), |(), (scope, builder)| scope.new_walk(builder.as_visitor()).cast()) .then((), |(), ((_, builder), _)| builder.build()) .map(error, |mut error, result| { result.map(|x| effectful::bound::Dynamic(X::$variant( <<$value as Build<'ctx, M, E>>::Builder as BuilderTypes>::unwrap_output(x) ))).map_err(|err| { error.$variant = Some(err); error }) }) .cast() }))* .map((), |_, (_, result)| match result { Ok(value) => Ok(value), Err(err) => Err(__Error::__Guess { $($variant: err.$variant.unwrap()),* }), }).cast() } } }; }; }