1#[macro_export]
2macro_rules! java_inner {
3 (toplevel {}) => {};
4 (toplevel { package $name:ident; $($remaining:tt)* }) => {
5 java_inner!(toplevel { $($remaining)* });
6 };
7 (toplevel { public class $name:ident {
8 $($kind:ident $var:ident;)*
9 ---
10 $($inner:tt)*
11 } $($remaining:tt)* }) => {
12 #[derive(Clone, Debug, Default)]
13 pub struct $name {
14 $($var: java_inner!(kind $kind)),*
15 }
16 java_inner!(class($name) { $($inner)* });
17 java_inner!(toplevel { $($remaining)* });
18 };
19 (toplevel { public class $name:ident {
20 $($inner:tt)*
21 } $($remaining:tt)* }) => {
22 java_inner!(toplevel { public class $name {
23 ---
24 $($inner)*
25 } });
26 };
27
28 (class($class:ident) {}) => {};
29 (class($class:ident) { public static void main(String[] $args:ident) {
30 $($inner:tt)*
31 } $($remaining:tt)* }) => {
32 fn main() {
33 #[allow(unused_mut, unused_variables)]
34 let mut $args: Vec<String> = std::env::args().skip(1).collect();
35 java_inner!(stmt($class) { $($inner)* });
36 }
37 java_inner!(class($class) { $($remaining)* });
38 };
39 (class($class:ident) { public $constructor:ident($self:ident$(, $kind:ident $var:ident)*) {
40 $($inner:tt)*
41 } $($remaining:tt)* }) => {
42 impl $class {
43 pub fn init($self: &mut Self, $($var: java_inner!(kind $kind)),*) {
44 java_inner!(stmt($class) { $($inner)* });
45 }
46 pub fn new($($var: java_inner!(kind $kind)),*) -> Self {
47 assert_eq!(stringify!($class), stringify!($constructor), "constructor does not share name with class");
48 let mut me = Self::default();
49 Self::init(&mut me, $($var),*);
50 me
51 }
52 }
53 java_inner!(class($class) { $($remaining)* });
54 };
55 (class($class:ident) { public $ret:ident $fn:ident($self:ident$(, $kind:ident $var:ident)*) {
56 $($inner:tt)*
57 } $($remaining:tt)* }) => {
58 impl $class {
59 pub fn $fn($self: &mut Self, $($var: java_inner!(kind $kind)),*) -> java_inner!(kind $ret) {
60 java_inner!(stmt($class) { $($inner)* });
61 }
62 }
63 java_inner!(class($class) { $($remaining)* });
64 };
65 (class($class:ident) { public static $ret:ident $fn:ident($($kind:ident $var:ident),*) {
66 $($inner:tt)*
67 } $($remaining:tt)* }) => {
68 impl $class {
69 pub fn $fn($($var: java_inner!(kind $kind)),*) -> java_inner!(kind $ret) {
70 java_inner!(stmt($class) { $($inner)* });
71 }
72 }
73 java_inner!(class($class) { $($remaining)* });
74 };
75
76 (stmt($class:ident) {}) => {};
77 (stmt($class:ident) { System.out.println($($out:tt)*); $($remaining:tt)* }) => {
78 println!("{}", java_inner!(expr($class) { $($out)* }));
79 java_inner!(stmt($class) { $($remaining)* });
80 };
81 (stmt($class:ident) { System.out.println_debug($($out:tt)*); $($remaining:tt)* }) => {
82 println!("{:?}", java_inner!(expr($class) { $($out)* }));
83 java_inner!(stmt($class) { $($remaining)* });
84 };
85 (stmt($class:ident) { System.out.print($($out:tt)*); $($remaining:tt)* }) => {
86 print!("{}", java_inner!(expr($class) { $($out)* }));
87 java_inner!(stmt($class) { $($remaining)* });
88 };
89 (stmt($class:ident) { $kind:ident $name:ident = ($($value:tt)*); $($remaining:tt)* }) => {
90 #[allow(unused_mut)]
91 let mut $name: java_inner!(kind $kind) = java_inner!(expr($class) { $($value)* });
92 java_inner!(stmt($class) { $($remaining)* });
93 };
94 (stmt($class:ident) { $kind:ident $name:ident = $value:expr; $($remaining:tt)* }) => {
95 java_inner!(stmt($class) { $kind $name = ($value); $($remaining)* });
96 };
97 (stmt($class:ident) { ($name:expr) = ($($val:tt)*); $($remaining:tt)* }) => {
98 $name = java_inner!(expr($class) { $($val)* });
99 java_inner!(stmt($class) { $($remaining)* });
100 };
101 (stmt($class:ident) { ($name:expr) = $val:expr; $($remaining:tt)* }) => {
102 java_inner!(stmt($class) { ($name) = ($val); $($remaining)* });
103 };
104 (stmt($class:ident) { $name:ident = $val:expr; $($remaining:tt)* }) => {
105 java_inner!(stmt($class) { ($name) = ($val); $($remaining)* });
106 };
107 (stmt($class:ident) { ($name:expr) += $val:expr; $($remaining:tt)* }) => {
108 $name += $val;
109 java_inner!(stmt($class) { $($remaining)* });
110 };
111 (stmt($class:ident) { ($name:expr) -= $val:expr; $($remaining:tt)* }) => {
112 $name -= java_inner!(expr($class) { $val });
113 java_inner!(stmt($class) { $($remaining)* });
114 };
115 (stmt($class:ident) { $name:ident++; $($remaining:tt)* }) => {
116 $name += 1;
117 java_inner!(stmt($class) { $($remaining)* });
118 };
119 (stmt($class:ident) { $name:ident--; $($remaining:tt)* }) => {
120 $name -= 1;
121 java_inner!(stmt($class) { $($remaining)* });
122 };
123 (stmt($class:ident) { return ($($val:tt)*); $($remaining:tt)* }) => {
124 return java_inner!(expr($class) { $($val)* }) as _;
125 java_inner!(stmt($class) { $($remaining)* });
128 };
129 (stmt($class:ident) { return $val:expr; $($remaining:tt)* }) => {
130 java_inner!(stmt($class) { return ($val); $($remaining)* });
131 };
132 (stmt($class:ident) { break; $($remaining:tt)* }) => {
133 break;
134 java_inner!(stmt($class) { $($remaining)* });
137 };
138 (stmt($class:ident) { continue; $($remaining:tt)* }) => {
139 continue;
140 java_inner!(stmt($class) { $($remaining)* });
143 };
144 (stmt($class:ident) { for (($($pre:tt)*); ($($cond:tt)*); ($($post:tt)*)) {
145 $($inner:tt)*
146 } $($remaining:tt)* }) => {
147 java_inner!(stmt($class) { $($pre)* });
148 while java_inner!(expr($class) { $($cond)* }) {
149 java_inner!(stmt($class) { $($inner)* });
150 java_inner!(stmt($class) { $($post)* });
151 }
152 java_inner!(stmt($class) { $($remaining)* });
153 };
154 (stmt($class:ident) { if ($($cond:tt)*) {
155 $($success:tt)*
156 } $(else if ($($elseif_cond:tt)*) {
157 $($elseif_success:tt)*
158 })* $(else {
160 $($otherwise:tt)*
161 })*; $($remaining:tt)* }) => {
162 if java_inner!(expr($class) { $($cond)* }) {
163 java_inner!(stmt($class) { $($success)* });
164 } $(else if java_inner!(expr($class) { $($elseif_cond)* }) {
165 java_inner!(stmt($class) { $($elseif_success)* });
166 })* $(else {
167 java_inner!(stmt($class) { $($otherwise)* });
168 })*
169 java_inner!(stmt($class) { $($remaining)* });
170 };
171 (stmt($class:ident) { switch($($search:tt)*) {
172 $(case ($match:expr) {
173 $($success:tt)*
174 })*
175 $(default {
177 $($default:tt)*
178 })*
179 } $($remaining:tt)* }) => {
180 loop {
181 #[allow(unused_assignments)]
182 let mut fallthrough = false;
183 let search = java_inner!(expr($class) { $($search)* });
184
185 $(
186 if fallthrough || search == $match {
187 #[allow(unused_assignments)]
188 { fallthrough = true; }
189 java_inner!(stmt($class) { $($success)* });
190 }
191 )*
192
193 $(java_inner!(stmt($class) { $($default)* });)*
194 #[allow(unreachable_code)]
195 { break; }
196 }
197 java_inner!(stmt($class) { $($remaining)* });
198 };
199 (stmt($class:ident) { while ($($cond:tt)*) {
200 $($inner:tt)*
201 } $($remaining:tt)* }) => {
202 while java_inner!(expr($class) { $($cond)* }) {
203 java_inner!(stmt($class) { $($inner)* });
204 }
205 java_inner!(stmt($class) { $($remaining)* });
206 };
207 (stmt($class:ident) { $val:ident.$fn:ident($(($($var:tt)*)),*); $($remaining:tt)* }) => {
209 $val::$fn($(java_inner!(expr($class) { $($var)* })),*);
210 java_inner!(stmt($class) { $($remaining)* });
211 };
212 (stmt($class:ident) { $val:ident.$fn:ident($($var:expr),*); $($remaining:tt)* }) => {
213 java_inner!(stmt($class) { $val.$fn($(($var)),*); $($remaining)* });
214 };
215 (stmt($class:ident) { $fn:ident($(($($var:tt)*)),*); $($remaining:tt)* }) => {
216 $class::$fn($(java_inner!(expr($class) { $($var)* })),*);
217 java_inner!(stmt($class) { $($remaining)* });
218 };
219 (stmt($class:ident) { $fn:ident($($var:expr),*); $($remaining:tt)* }) => {
220 java_inner!(stmt($class) { $fn($(($var)),*); $($remaining)* });
221 };
222
223 (expr($class:ident) { $array:ident[$index:expr] }) => {{
224 assert!($index >= 0);
225 &mut $array[$index as usize]
226 }};
227 (expr($class:ident) { $array:ident.length }) => {{
228 $array.len() as i32
229 }};
230 (expr($class:ident) { ($($var1:tt)*) $(+ ($($var2:tt)*))+ }) => {{
231 use jrust::*;
232 java_inner!(expr($class) { $($var1)* })
233 $(.add(java_inner!(expr($class) { $($var2)* })))*
234 }};
235 (expr($class:ident) { $var:ident++ }) => {{
236 let old = $var;
237 $var += 1;
238 old
239 }};
240 (expr($class:ident) { $var1:ident $op:tt $var2:ident }) => {{
241 java_inner!(expr($class) { ($var1) $op ($var2) })
242 }};
243 (expr($class:ident) { ($($var1:tt)*) $op:tt ($($var2:tt)*) }) => {{
244 (java_inner!(expr($class) { $($var1)* }) as i64) $op (java_inner!(expr($class) { $($var2)* }) as i64)
245 }};
246 (expr($_class:ident) { new $class:ident($(($($var:tt)*)),*) }) => {{
247 &mut $class::new($(java_inner!(expr($class) { $($var)* })),*)
248 }};
249 (expr($_class:ident) { new $class:ident($($var:expr),*) }) => {{
250 java_inner!(expr($class) { new $class($(($var)),*) })
251 }};
252 (expr($class:ident) { $fn:ident($(($($var:tt)*)),*) }) => {
254 $class::$fn($(java_inner!(expr($class) { $($var)* })),*);
255 };
256 (expr($class:ident) { $fn:ident($($var:expr),*) }) => {
257 java_inner!(expr($class) { $fn($(($var)),*) });
258 };
259 (expr($class:ident) { $expr:expr }) => {{
260 $expr
261 }};
262
263 (kind byte) => { i8 };
264 (kind short) => { i16 };
265 (kind int) => { i32 };
266 (kind long) => { i64 };
267 (kind void) => { () };
268 (kind $name:ident) => { &mut $name };
269}
270#[macro_export]
271macro_rules! java {
272 ($($code:tt)*) => {
273 java_inner!(toplevel { $($code)* });
274 }
275}
276
277use std::fmt::Display;
278
279pub trait JavaAdd<T> {
280 type Target;
281
282 fn add(self, other: T) -> Self::Target;
283}
284
285impl<T: Display> JavaAdd<T> for String {
286 type Target = Self;
287
288 fn add(mut self, other: T) -> Self::Target {
289 use std::fmt::Write;
290 write!(self, "{}", other).unwrap();
291 self
292 }
293}
294impl<'a, T: Display> JavaAdd<T> for &'a str {
295 type Target = String;
296
297 fn add(self, other: T) -> Self::Target {
298 JavaAdd::<T>::add(String::from(self), other)
299 }
302}
303
304macro_rules! impl_add {
305 ($($primitive:ident),*) => {
306 $(impl<T: Into<i64>> JavaAdd<T> for $primitive {
307 type Target = i64;
308
309 fn add(self, other: T) -> Self::Target {
310 i64::from(self) + other.into()
311 }
312 })*
313 }
314}
315
316impl_add!(i8, i16, i32, i64);