summaryrefslogtreecommitdiffstats
path: root/tests/ui/macros/rfc-3086-metavar-expr/feature-gate-macro_metavar_expr.rs
blob: d05cd1b31bc12735fc3e06ca581376b055942941 (plain)
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
141
142
143
144
145
146
147
148
// run-pass

#![feature(macro_metavar_expr)]

/// Count the number of idents in a macro repetition.
macro_rules! count_idents {
    ( $( $i:ident ),* ) => {
        ${count(i)}
    };
}

/// Count the number of idents in a 2-dimensional macro repetition.
macro_rules! count_idents_2 {
    ( $( [ $( $i:ident ),* ] ),* ) => {
        ${count(i)}
    };
}

/// Mostly counts the number of OUTER-MOST repetitions
macro_rules! count_depth_limits {
    ( $( { $( [ $( $outer:ident : ( $( $inner:ident )* ) )* ] )* } )* ) => {
        (
            (
                ${count(inner)},
                ${count(inner, 0)},
                ${count(inner, 1)},
                ${count(inner, 2)},
                ${count(inner, 3)},
            ),
            (
                ${count(outer)},
                ${count(outer, 0)},
                ${count(outer, 1)},
                ${count(outer, 2)},
            ),
        )
    };
}

/// Produce (index, length) pairs for literals in a macro repetition.
/// The literal is not included in the output, so this macro uses the
/// `ignore` meta-variable expression to create a non-expanding
/// repetition binding.
macro_rules! enumerate_literals {
    ( $( ($l:stmt) ),* ) => {
        [$( ${ignore(l)} (${index()}, ${length()}) ),*]
    };
}

/// Produce index and length tuples for literals in a 2-dimensional
/// macro repetition.
macro_rules! enumerate_literals_2 {
    ( $( [ $( ($l:literal) ),* ] ),* ) => {
        [
            $(
                $(
                    (
                        ${index(1)},
                        ${length(1)},
                        ${index(0)},
                        ${length(0)},
                        $l
                    ),
                )*
            )*
        ]
    };
}

/// Generate macros that count idents and then add a constant number
/// to the count.
///
/// This macro uses dollar escaping to make it unambiguous as to which
/// macro the repetition belongs to.
macro_rules! make_count_adders {
    ( $( $i:ident, $b:literal );* ) => {
        $(
            macro_rules! $i {
                ( $$( $$j:ident ),* ) => {
                    $b + $${count(j)}
                };
            }
        )*
    };
}

make_count_adders! { plus_one, 1; plus_five, 5 }

/// Generate a macro that allows selection of a particular literal
/// from a sequence of inputs by their identifier.
///
/// This macro uses dollar escaping to make it unambiguous as to which
/// macro the repetition belongs to, and to allow expansion of an
/// identifier the name of which is not known in the definition
/// of `make_picker`.
macro_rules! make_picker {
    ( $m:ident => $( $i:ident ),* ; $p:ident ) => {
        macro_rules! $m {
            ( $( $$ $i:literal ),* ) => {
                $$ $p
            };
        }
    };
}

make_picker!(first => a, b; a);

make_picker!(second => a, b; b);

fn main() {
    assert_eq!(count_idents!(a, b, c), 3);
    assert_eq!(count_idents_2!([a, b, c], [d, e], [f]), 6);
    assert_eq!(
        count_depth_limits! {
            {
                [ A: (a b c) D: (d e f) ]
                [ G: (g h) I: (i j k l m) ]
                [ N: (n) ]
            }
            {
                [ O: (o) P: (p q) R: (r s) ]
                [ T: (t u v w x y z) ]
            }
        },
        ((26, 2, 5, 9, 26), (9, 2, 5, 9))
    );
    assert_eq!(enumerate_literals![("foo"), ("bar")], [(0, 2), (1, 2)]);
    assert_eq!(
        enumerate_literals_2![
            [("foo"), ("bar"), ("baz")],
            [("qux"), ("quux"), ("quuz"), ("xyzzy")]
        ],
        [
            (0, 2, 0, 3, "foo"),
            (0, 2, 1, 3, "bar"),
            (0, 2, 2, 3, "baz"),

            (1, 2, 0, 4, "qux"),
            (1, 2, 1, 4, "quux"),
            (1, 2, 2, 4, "quuz"),
            (1, 2, 3, 4, "xyzzy"),
        ]
    );
    assert_eq!(plus_one!(a, b, c), 4);
    assert_eq!(plus_five!(a, b), 7);
    assert_eq!(first!(1, 2), 1);
    assert_eq!(second!(1, 2), 2);
}