1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
//! # Design
//!

#![cfg_attr(all(not(test), not(feature = "std")), no_std)]
#![deny(elided_lifetimes_in_paths)]

#[cfg(feature = "alloc")]
extern crate alloc;

pub mod any;
// mod build;
pub mod protocol;
pub mod symbol;
pub mod hkt;
// mod walk;

// pub mod impls;
// pub mod transform;

// pub use build::Build;
// pub use build::Builder;
//
// pub use walk::Walk;
// pub use walk::Walker;

// pub use build::*;
// pub use walk::*;

#[macro_export]
macro_rules! Build {
    {
        $(#[$($attr:tt)*])*
        $vis:vis struct $name:ident {$(
            $field:ident: $type:ty
        ),* $(,)?}
    } => {
        const _: () = {
            impl<'ctx> $crate::Build<'ctx> for $name {
                type Builder = StructBuilder;
            }

            #[derive(Default)]
            $vis struct StructBuilder {$(
                $field: Option<$type>
            ),*}

            impl<'ctx> $crate::Builder<'ctx> for StructBuilder {
                type Error = ();

                type Value = $name;

                fn as_visitor(&mut self) -> &mut dyn $crate::protocol::Implementer<'ctx> {
                    self
                }

                fn build(self) -> Result<Self::Value, Self::Error> {
                    if let StructBuilder {$($field: Some($field)),*} = self {
                        Ok($name {$($field),*})
                    } else {
                        Err(())
                    }
                }
            }

            $crate::protocol::implementer! {
                impl['ctx] StructBuilder = [

                ];
            }

            impl<'ctx> $crate::Walk<'ctx> for $name {
                type Walker = StructWalker;
            }

            $vis struct StructWalker {
                value: Option<$name>,
                hint_given: bool,
            }

            impl From<$name> for StructWalker {
                fn from(value: $name) -> Self {
                    Self {
                        value: Some(value),
                        hint_given: false
                    }
                }
            }

            impl<'ctx> $crate::Walker<'ctx> for StructWalker {
                type Error = ();

                type Output = ();

                fn walk(
                    &mut self,
                    visitor: &mut dyn $crate::protocol::Implementer<'ctx>
                ) -> Result<Self::Output, Self::Error> {
                    use $crate::protocol::ImplementerExt;
                    // Want kinds for tags.
                    if let Some(interface) = visitor.interface_for::
                        <$crate::builtins::visitor::request_hint>() {
                        interface.as_object().visit(&mut self);
                    }
                    $(
                        <$type as $crate::Walk>::Walker::from(self.0.$field)
                            .walk(visitor);
                    )*
                    todo!()
                }
            }
        };
    };
}