1#[macro_export]
2macro_rules! type_error_at {
3 ($location:expr, $($arg:tt)*) => {
4 TsTypeError {
5 message: format!($($arg)*),
6 location: $location.to_string(),
7 }
8 };
9}
10
11#[macro_export]
12macro_rules! ts_tt {
13
14 (( $single:tt )) => {{
16 ts_tt!($single)
17 }};
18
19 (( # $var:ident )) => {{
21 $var.clone()
22 }};
23
24 (( $($items:tt)+ )) => {{
26 let inner = ts_type!($($items)*);
27 match inner {
28 $crate::TsType::Intersection(_) => $crate::TsType::Paren(Box::new(inner)),
29 $crate::TsType::Union(_) => $crate::TsType::Paren(Box::new(inner)),
30 _ => inner, }
32 }};
33
34 ([ $first:tt $($items:tt)* ]) => {{
36 let tuple = $crate::TsType::Tuple(vec![]);
37 let mut stack = vec![tuple];
38 let mut first = ts_tt!($first);
39 $crate::build_ts_type!(stack first $($items)*)
40 }};
41
42 ($base:tt) => {{
44 $crate::TsType::Base(stringify!($base).to_string())
45 }};
46}
47
48#[macro_export]
49macro_rules! build_ts_type {
50
51 ($stack:ident $ty:ident [] $($rest:tt)*) => {{
53 $ty = $ty.in_array();
54 $crate::build_ts_type!($stack $ty $($rest)*)
55 }};
56
57 ($stack:ident $ty:ident [ $($keys:tt)+ ] $($rest:tt)*) => {{
59 $ty = $ty.property(Box::new(ts_type!($($keys)+)));
60 $crate::build_ts_type!($stack $ty $($rest)*)
61 }};
62
63 ($stack:ident $ty:ident & $other:tt $($rest:tt)*) => {{
65 let intersection = $crate::TsType::Intersection(vec![$ty]);
66 $stack.push(intersection);
67 $ty = $crate::ts_tt!($other);
68 $crate::build_ts_type!($stack $ty $($rest)*)
69 }};
70
71 ($stack:ident $ty:ident | $other:tt $($rest:tt)*) => {{
73 let _union = $crate::TsType::Union(vec![$ty]);
74 $stack.push(_union);
75 $ty = $crate::ts_tt!($other);
76 $crate::build_ts_type!($stack $ty $($rest)*)
77 }};
78
79 ($stack:ident $ty:ident < $arg:tt $($rest:tt)*) => {{
81 $ty = $ty.as_generic(vec![]);
82 $stack.push($ty);
83 let mut arg = $crate::ts_tt!($arg);
84 $crate::build_ts_type!($stack arg $($rest)*)
85 }};
86
87 ($stack:ident $ty:ident , $next:tt $($rest:tt)*) => {{
89 let top: $crate::TsType = $stack.pop().unwrap_or_else(|| {
90 panic!("Unexpected `,` found.");
91 });
92 $stack.push(top.join($ty).unwrap());
93 #[allow(unused_mut)]
94 let mut next = $crate::ts_tt!($next);
95 build_ts_type!($stack next $($rest)*)
96 }};
97
98 ($stack:ident $arg:ident > $($rest:tt)*) => {{
100 let mut ty = $arg;
101 loop {
102 let top: $crate::TsType = $stack.pop().unwrap_or_else(|| {
103 panic!("Unmatched `>` found.");
104 });
105 ty = top.join(ty).unwrap();
106 if let $crate::TsType::Generic(_, _) = ty {
107 break;
108 } else if $stack.is_empty() {
109 panic!("Unmatched `>` found.");
110 }
111 }
112 $crate::build_ts_type!($stack ty $($rest)*)
113 }};
114
115 ($stack:ident $arg:ident >> $($rest:tt)*) => {{
117 let mut ty = $arg;
118 let mut count = 0;
119 loop {
120 let top: $crate::TsType = $stack.pop().unwrap_or_else(|| {
121 panic!("Unmatched `>` found.");
122 });
123 ty = top.join(ty).unwrap();
124 if let $crate::TsType::Generic(_, _) = ty {
125 count += 1;
126 }
127 if count == 2 {
128 break;
129 } else if $stack.is_empty() {
130 panic!("Unmatched `>` found.");
131 }
132 }
133 $crate::build_ts_type!($stack ty $($rest)*)
134 }};
135
136 ($stack:ident $ty:ident) => {{
138 let mut ty = $ty;
139 for _ in 0..$stack.len() {
140 let top: $crate::TsType = $stack.pop().unwrap();
141 ty = top.join(ty).unwrap();
142 }
143 ty
144 }};
145}
146
147#[macro_export]
149macro_rules! ts_type {
150
151 (| $member:tt $($rest:tt)*) => {{
153 let _union = $crate::TsType::Union(vec![]);
154 let mut stack = vec![_union];
155 let mut member = $crate::ts_tt!($member);
156 $crate::build_ts_type!(stack member $($rest)*)
157 }};
158
159 ($elem:tt [] $($rest:tt)*) => {{
161 let mut stack = vec![];
162 #[allow(unused_mut)]
163 let mut array = $crate::TsType::Array(Box::new($crate::ts_tt!($elem)));
164 $crate::build_ts_type!(stack array $($rest)*)
165 }};
166
167 ($object:tt [ $($key:tt)+ ] $($rest:tt)*) => {{
169 let mut stack = vec![];
170 let mut object = $crate::TsType::IndexedAccess(Box::new(ts_tt!($object)), Box::new(ts_type!($($key)+)));
171 build_ts_type!(stack object $($rest)*)
172 }};
173
174 ($generic:tt < $arg:tt $($rest:tt)*) => {{
176 let generic = $crate::TsType::Generic(Box::new(ts_tt!($generic)), vec![]);
177 let mut stack = vec![generic];
178 #[allow(unused_mut)]
179 let mut arg = ts_tt!($arg);
180 build_ts_type!(stack arg $($rest)*)
181 }};
182
183 ($base:tt $($rest:tt)*) => {{
185 let mut stack = vec![];
186 #[allow(unused_mut)]
187 let mut base = $crate::ts_tt!($base);
188 $crate::build_ts_type!(stack base $($rest)*)
189 }};
190}