1#[cfg(test)]
4use crate::Pattern;
5
6#[macro_export]
8macro_rules! m {
9 (atom $i:ident) => {{ $crate::atom(stringify!($i)) }};
10 (atom $l:literal) => {{ $crate::atom($l) }};
11 (atom ~) => {{ $crate::silence() }};
12 (atom ($t:tt) $elongate:literal $($ts:tt)*) => {{
13 let rate = $crate::Rational::new(1, $elongate);
14 let p = $crate::Pattern::into_dyn($crate::Pattern::rate(m!(atom $t), rate));
15 let ps = m!(group $($ts)*);
16 let silence = (0..$elongate-1).map(|_| $crate::Pattern::into_dyn($crate::silence()));
17 let elongated = $crate::mini::Chain(std::iter::once(p).chain(silence));
18 $crate::mini::Chain(elongated.chain(ps))
19 }};
20
21 (group $i:ident($a:literal,$b:literal) $($ts:tt)*) => {{
22 compile_error!("Euclidean patterns not yet supported")
23 }};
24 (group $l:literal($a:literal,$b:literal) $($ts:tt)*) => {{
25 compile_error!("Euclidean patterns not yet supported")
26 }};
27 (group {{$e:expr}} $($ts:tt)*) => {{
28 compile_error!("Expressions unhandled")
29 }};
30 (group $i:ident _ _ _ _ _ _ _ $($ts:tt)*) => {{ m!(atom ($i) 8 $($ts)*) }};
31 (group $i:ident _ _ _ _ _ _ $($ts:tt)*) => {{ m!(atom ($i) 7 $($ts)*) }};
32 (group $i:ident _ _ _ _ _ $($ts:tt)*) => {{ m!(atom ($i) 6 $($ts)*) }};
33 (group $i:ident _ _ _ _ $($ts:tt)*) => {{ m!(atom ($i) 5 $($ts)*) }};
34 (group $i:ident _ _ _ $($ts:tt)*) => {{ m!(atom ($i) 4 $($ts)*) }};
35 (group $i:ident _ _ $($ts:tt)*) => {{ m!(atom ($i) 3 $($ts)*) }};
36 (group $i:ident _ $($ts:tt)*) => {{ m!(atom ($i) 2 $($ts)*) }};
37 (group $i:ident $($ts:tt)*) => {{ m!(atom ($i) 1 $($ts)*) }};
38 (group $l:literal _ _ _ _ _ _ _ $($ts:tt)*) => {{ m!(atom ($l) 8 $($ts)*) }};
39 (group $l:literal _ _ _ _ _ _ $($ts:tt)*) => {{ m!(atom ($l) 7 $($ts)*) }};
40 (group $l:literal _ _ _ _ _ $($ts:tt)*) => {{ m!(atom ($l) 6 $($ts)*) }};
41 (group $l:literal _ _ _ _ $($ts:tt)*) => {{ m!(atom ($l) 5 $($ts)*) }};
42 (group $l:literal _ _ _ $($ts:tt)*) => {{ m!(atom ($l) 4 $($ts)*) }};
43 (group $l:literal _ _ $($ts:tt)*) => {{ m!(atom ($l) 3 $($ts)*) }};
44 (group $l:literal _ $($ts:tt)*) => {{ m!(atom ($l) 2 $($ts)*) }};
45 (group $l:literal $($ts:tt)*) => {{ m!(atom ($l) 1 $($ts)*) }};
46 (group ~ _ _ _ _ _ _ _ $($ts:tt)*) => {{ m!(atom (~) 8 $($ts)*) }};
47 (group ~ _ _ _ _ _ _ $($ts:tt)*) => {{ m!(atom (~) 7 $($ts)*) }};
48 (group ~ _ _ _ _ _ $($ts:tt)*) => {{ m!(atom (~) 6 $($ts)*) }};
49 (group ~ _ _ _ _ $($ts:tt)*) => {{ m!(atom (~) 5 $($ts)*) }};
50 (group ~ _ _ _ $($ts:tt)*) => {{ m!(atom (~) 4 $($ts)*) }};
51 (group ~ _ _ $($ts:tt)*) => {{ m!(atom (~) 3 $($ts)*) }};
52 (group ~ _ $($ts:tt)*) => {{ m!(atom (~) 2 $($ts)*) }};
53 (group ~ $($ts:tt)*) => {{ m!(atom (~) 1 $($ts)*) }};
54 (group $l:literal $($ts:tt)*) => {{
55 let p = $crate::Pattern::into_dyn($crate::atom($l));
56 let ps = m!(group $($ts)*);
57 $crate::mini::Chain(std::iter::once(p).chain(ps))
58 }};
59 (group [$($a:tt)*], [$($b:tt)*]) => {{
60 let stack = $crate::stack([
61 $crate::fastcat(m!(group $($a)*)).into_dyn(),
62 $crate::fastcat(m!(group $($b)*)).into_dyn(),
63 ]).into_dyn();
64 std::iter::once(stack)
65 }};
66 (group [$($fastcat:tt)*] $($ts:tt)*) => {{
67 let p = $crate::Pattern::into_dyn(m!($($fastcat)*));
68 let ps = m!(group $($ts)*);
69 $crate::mini::Chain(std::iter::once(p).chain(ps))
70 }};
71 (group <($($slowcat:tt)*)> $($ts:tt)*) => {{
72 let p = $crate::Pattern::into_dyn($crate::slowcat(m!(group $($slowcat)*)));
73 let ps = m!(group $($ts)*);
74 $crate::mini::Chain(std::iter::once(p).chain(ps))
75 }};
76 (group $($ts:tt)*) => {{
77 []
78 }};
79
80 ($($ts:tt)*) => {{
81 $crate::fastcat(m!(group $($ts)*))
82 }};
83}
84
85pub struct Chain<A, B>(pub std::iter::Chain<A, B>);
90
91impl<A, B> Iterator for Chain<A, B>
92where
93 A: Iterator,
94 B: Iterator<Item = A::Item>,
95{
96 type Item = A::Item;
97 fn next(&mut self) -> Option<Self::Item> {
98 self.0.next()
99 }
100 fn size_hint(&self) -> (usize, Option<usize>) {
101 self.0.size_hint()
102 }
103}
104
105impl<A, B> ExactSizeIterator for Chain<A, B>
106where
107 A: Iterator,
108 B: Iterator<Item = A::Item>,
109{
110 fn len(&self) -> usize {
111 let (lower, upper) = self.size_hint();
112 let upper = upper.expect("no upperbound on iterator");
113 assert_eq!(lower, upper);
114 upper
115 }
116}
117
118#[test]
119fn test_ident_atom() {
120 dbg!(m![bd].debug());
121}
122
123#[test]
124fn test_ident_seq() {
125 dbg!(m![bd sn cp td].debug());
126}
127
128#[test]
129fn test_literal_seq() {
130 dbg!(m![0 1 2 3 4].debug());
131}
132
133#[test]
134fn test_literal_fastcat() {
135 dbg!(m![0 [1 2] 3 [4 5]].debug());
136}
137
138#[test]
139fn test_fastcat() {
140 let a = m![bd sn].query_cycle().collect::<Vec<_>>();
141 let b = m![[[[bd sn]]]].query_cycle().collect::<Vec<_>>();
142 assert_eq!(a, b);
143}
144
145#[test]
146fn test_rest() {
147 dbg!(m![0 ~ 2 ~ ~ 6 ~ 8].debug());
148}
149
150#[test]
151fn test_elongate() {
152 dbg!(m![bd _ _ _ sn _].debug());
153 dbg!(m![0 _ _ _ 1 _].debug());
154}
155
156#[test]
157fn test_slowcat() {
158 use crate::span;
159 dbg!(m![a b <(c d)>].debug_span(span!(0 / 1, 4 / 1)));
160}
161
162#[test]
163fn test_stack() {
164 dbg!(m![[bd bd], [sn sn sn]].debug());
165}