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
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140

#[macro_export(local_inner_macros)]
macro_rules! generate_trait_def {
    {
        $caller:tt
        name = [{ $name:ident }]
        bounds = [{ $($bounds:tt)+ }]
        getters = [{ $(
            { $getter:ident $t:ty }
        )* }]
    } => {
        $crate::tt_call::tt_return! {
            $caller
            trait_def = [{
                pub trait $name: $($bounds)+ {
                    $(fn $getter(&self) -> $t;)*
                }
            }]
        }
    };
}


#[macro_export(local_inner_macros)]
macro_rules! generate_trait_impl {
    {
        $caller:tt
        name = [{ $name:ident }]
        bounds = [{ $($bounds:tt)+ }]
        getters = [{ $(
            { $getter:ident $t:ty }
        )* }]
    } => {
        $crate::tt_call::tt_return! {
            $caller
            trait_impl = [{
                impl<T: $($bounds)+> $name for T {
                    $(fn $getter(&self) -> $t {
                        $crate::Provide::<$t>::provide(self)
                    })*
                }
            }]
        }
    };
}

#[macro_export(local_inner_macros)]
macro_rules! private_define_interface {
    {
        $caller:tt
        input = [{ $($input:tt)* }]
    } => {
        $crate::tt_call::tt_call! {
            macro = [{ parse_trait_def }]
            input = [{ $($input)* }]
            ~~> private_define_interface! {
                $caller
            }
        }
    };
    {
        $caller:tt
        name = [{ $name:ident }]
        body = [{ $(
            fn $getter:ident(&self) -> $t:ty;
        )* }]
        $(bound = [{ $($bound:tt)* }])*
    } => {
        $crate::tt_call::tt_call! {
            macro = [{ join }]
            sep = [{ + }]
            $(item = [{ $($bound)* }])*
            $(item = [{ $crate::Provide<$t> }])*
            ~~> private_define_interface! {
                $caller
                name = [{ $name }]
                getters = [{ $(
                    { $getter $t }
                )* }]
            }
        }
    };
    {
        $caller:tt
        name = [{ $name:ident }]
        getters = [{ $($getters:tt)* }]
        joined = [{ $($joined:tt)* }]
    } => {
        $crate::tt_call::tt_call! {
            macro = [{ generate_trait_def }]
            name = [{ $name }]
            bounds = [{ $($joined)* }]
            getters = [{ $($getters)* }]
            ~~> private_define_interface! {
                $caller
                name = [{ $name }]
                getters = [{ $($getters)* }]
                bounds = [{ $($joined)* }]
            }
        }
    };
    {
        $caller:tt
        name = [{ $name:ident }]
        getters = [{ $($getters:tt)* }]
        bounds = [{ $($bounds:tt)* }]
        trait_def = [{ $($trait_def:tt)* }]
    } => {
        $crate::tt_call::tt_call! {
            macro = [{ generate_trait_impl }]
            name = [{ $name }]
            bounds = [{ $($bounds)* }]
            getters = [{ $($getters)* }]
            ~~> private_define_interface! {
                $caller
                trait_def = [{ $($trait_def)* }]
            }
        }
    };
    {
        $caller:tt
        trait_def = [{ $($trait_def:tt)* }]
        trait_impl = [{ $($trait_impl:tt)* }]
    } => {
        $crate::tt_call::tt_return! {
            $caller
            result = [{ $($trait_def)* $($trait_impl)* }]
        }
    };
}

#[macro_export(local_inner_macros)]
macro_rules! define_interface {
    ($($input:tt)*) => (
        $crate::tt_call::tt_call! {
            macro = [{ private_define_interface }]
            input = [{ $($input)* }]
        }
    );
}