#[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<'ctx, M: 'ctx, E: effectful::environment::Environment> $crate::Build<'ctx, M, E> for $name
where
effectful::bound::Dynamic<$name>: effectful::environment::DynBind<E>,
$($type: $crate::Build<'ctx, M, E>,)*
$crate::builders::core::r#struct::StructBuilder<'ctx, __Info, M, E>: $crate::Builder<'ctx, E, Value = Self>
{
type Builder = $crate::builders::core::r#struct::StructBuilder<'ctx, __Info, M, E>;
}
#[derive(SendSync)]
$vis struct Builders<'ctx, M: 'ctx, E: effectful::environment::Environment>
where
$($type: $crate::Build<'ctx, M, E>),*
{
$($field: <$type as $crate::Build<'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<'ctx, M: 'ctx, E: effectful::environment::Environment>
where
$($type: $crate::Build<'ctx, M, E>),*
{
$($field(<<$type as $crate::Build<'ctx, M, E>>::Builder as $crate::BuilderTypes<E>>::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<'ctx, M: 'ctx, E: effectful::environment::Environment> ::core::fmt::Debug for Error<'ctx, M, E>
where
$($type: $crate::Build<'ctx, M, E>),*
{
fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
f.write_str(match self {
$(Error::$field(_) => stringify!($field)),*
})
}
}
impl<'ctx, M: 'ctx, E: effectful::environment::Environment> ::core::fmt::Display for Error<'ctx, M, E>
where
$($type: $crate::Build<'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<'ctx, M: 'ctx, E: effectful::environment::Environment> $crate::builders::core::r#struct::StructTypeInfo<'ctx, M, E> for __Info
where
effectful::bound::Dynamic<$name>: effectful::environment::DynBind<E>,
$($type: $crate::Build<'ctx, M, E>),*
{
type Builders = Builders<'ctx, M, E>;
type FieldMarker = Field;
type T = $name;
type Error = Error<'ctx, M, E>;
type Seed = ($(<<$type as $crate::Build<'ctx, M, E>>::Builder as $crate::BuilderTypes<E>>::Seed),*);
type ValueT = $crate::any::OwnedStatic<effectful::bound::Dynamic<$name>>;
const FIELD_COUNT: usize = {
[$(stringify!($field)),*].len()
};
#[inline(always)]
fn new_builders<'a>(seed: Self::Seed) -> effectful::environment::NativeForm<'a, Self::Builders, E> {
let ($($field),*) = seed;
todo!()
// $crate::effect::join(
// ($(<<$type as $crate::Build<'ctx, M, E>>::Builder as $crate::Builder::<E>>::from_seed($field),)*)
// ).map(|($($field,)*)| {
// Builders {
// $($field),*
// }
// })
}
fn from_builders<'a>(builders: Self::Builders) -> effectful::environment::NativeForm<'a, Result<effectful::bound::Dynamic<Self::T>, Self::Error>, E> {
use $crate::Builder;
todo!()
// $crate::effect::try_join(
// (
// $(|| builders.$field.build().map(|x| x.map_err(Error::$field)),)*
// )
// ).map(|result| match result {
// Ok(($($field,)*)) => Ok($name {
// $($field),*
// }),
// Err(err) => Err(err)
// })
}
fn as_visitor<'a>(
marker: Self::FieldMarker,
builders: &'a mut Self::Builders,
) -> $crate::protocol::DynVisitor<'a, 'ctx, E> {
use $crate::protocol::AsVisitor;
match marker {
$(Field::$field => builders.$field.as_visitor()),*
}
}
fn marker_from_index(index: usize) -> Option<Self::FieldMarker> {
match index {
$(field_index::$field => Some(Field::$field),)*
_ => None
}
}
fn marker_from_name(name: &str) -> Option<Self::FieldMarker> {
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::environment::DynBind<E>,
$($value: $crate::Build<'ctx, M, E>,)*
$(<<$value as Build<'ctx, M, E>>::Builder as BuilderTypes<E>>::Seed: Default,)*
$crate::builders::core::r#enum::EnumBuilder<'ctx, __Info, M, E>: $crate::Builder<'ctx, E, Value = Self>
{
type Builder = $crate::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<E>>::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<E>>::Error),*
},
$($variant(<<$value as $crate::Build<'ctx, M, E>>::Builder as BuilderTypes<E>>::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::builders::core::r#enum::EnumBuildInfo<'ctx, M, E> for __Info
where
effectful::bound::Dynamic<$name>: effectful::environment::DynBind<E>,
$($value: $crate::Build<'ctx, M, E>,)*
$(<<$value as Build<'ctx, M, E>>::Builder as BuilderTypes<E>>::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,
) -> NativeForm<'a, Self::Builders, E> {
match variant {
$(__Marker::$variant => {
Builder::<E>::from_seed(Default::default()).map((), |_, builder| __Builders::$variant(builder)).cast()
})*
}
}
fn finish_builder<'a>(
builder: Self::Builders,
) -> NativeForm<'a, Result<effectful::bound::Dynamic<Self::T>, 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<E>>::unwrap_output(x)))).map_err(__Error::$variant)).cast()),*
}
}
fn from_value<'a>(value: TypeName::T<'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<Self::VariantMarker> {
match name {
$(stringify!($variant) => Some(__Marker::$variant),)*
_ => None
}
}
fn marker_from_discriminant(discriminant: u32) -> Option<Self::VariantMarker> {
match discriminant {
$(variant_index::$variant => Some(__Marker::$variant),)*
_ => None
}
}
fn guess_variant<'a>(
seed: Self::Seed,
scope: DynRecoverableScope<'a, 'ctx, E>,
) -> NativeForm<'a, Result<effectful::bound::Dynamic<Self::T>, Self::Error>, E> {
use effectful::effective::EffectiveExt;
use effectful::short::ResultErrorExt;
E::value((scope, Err(__ErrorBuilder::<M, E> { A: None, B: None })))
$(.or_else_update((), |_, scope, result| {
let mut error = result.into_error();
<<$value as Build<M, E>>::Builder as Builder<_>>::from_seed(Default::default())
.map(scope, |scope, builder| (scope, builder))
.update((), |(), (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<E>>::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()
}
}
};
};
}