1macro_rules! emit_fatal_warning {
13 ($($arg:tt)+) => {{
14 use ::std::io::Write;
15
16 let maybe_err = ::std::write!(::std::io::stderr(), "fatal[artichoke-backend]: ");
25 drop(maybe_err);
26 let maybe_err = ::std::writeln!(::std::io::stderr(), $($arg)+);
27 drop(maybe_err);
28 }};
29}
30
31#[macro_export]
41macro_rules! unwrap_interpreter {
42 ($mrb:ident, to => $to:ident, or_else = ()) => {
43 let mrb = $mrb;
44 let mut interp = if let Ok(interp) = unsafe { $crate::ffi::from_user_data(mrb) } {
45 interp
46 } else {
47 return;
48 };
49 let mut arena = if let Ok(arena) =
50 $crate::gc::MrbGarbageCollection::create_arena_savepoint(&mut interp)
51 {
52 arena
53 } else {
54 return;
55 };
56 #[allow(unused_mut)]
57 let mut $to = $crate::Guard::new(arena.interp());
58 };
59 ($mrb:ident, to => $to:ident, or_else = $default:expr) => {
60 let mrb = $mrb;
61 let mut interp = if let Ok(interp) = unsafe { $crate::ffi::from_user_data(mrb) } {
62 interp
63 } else {
64 return $default;
65 };
66 let mut arena = if let Ok(arena) =
67 $crate::gc::MrbGarbageCollection::create_arena_savepoint(&mut interp)
68 {
69 arena
70 } else {
71 return $default;
72 };
73 #[allow(unused_mut)]
74 let mut $to = $crate::Guard::new(arena.interp());
75 };
76 ($mrb:ident, to => $to:ident) => {
77 unwrap_interpreter!($mrb, to => $to, or_else = $crate::sys::mrb_sys_nil_value())
78 };
79}
80
81#[doc(hidden)]
82pub mod argspec {
83 use std::ffi::CStr;
84
85 pub const NONE: &CStr = c"";
86 pub const REQ1: &CStr = c"o";
87 pub const OPT1: &CStr = c"|o";
88 pub const REQ1_OPT1: &CStr = c"o|o";
89 pub const REQ1_OPT2: &CStr = c"o|oo";
90 pub const REQ1_OPT3: &CStr = c"o|ooo";
91 pub const REQ1_REQBLOCK: &CStr = c"o&";
92 pub const REQ1_REQBLOCK_OPT1: &CStr = c"o&|o?";
93 pub const REQ1_REQBLOCK_OPT2: &CStr = c"o&|o?o?";
94 pub const REQ2: &CStr = c"oo";
95 pub const OPT2: &CStr = c"|oo";
96 pub const OPT2_OPTBLOCK: &CStr = c"&|o?o?";
97 pub const REQ2_OPT1: &CStr = c"oo|o";
98 pub const REST: &CStr = c"*";
99}
100
101#[macro_export]
113macro_rules! mrb_get_args {
114 ($mrb:ident, none) => {{
115 let mrb = $mrb;
116 unsafe {
117 $crate::sys::mrb_get_args(mrb, $crate::macros::argspec::NONE.as_ptr());
118 }
119 }};
120 ($mrb:ident, required = 1) => {{
121 let mrb = $mrb;
122 unsafe {
123 let mut req1 = std::mem::MaybeUninit::<$crate::sys::mrb_value>::uninit();
124 let argc = $crate::sys::mrb_get_args(mrb, $crate::macros::argspec::REQ1.as_ptr(), req1.as_mut_ptr());
125 match argc {
126 1 => req1.assume_init(),
127 _ => unreachable!("mrb_get_args should have raised"),
128 }
129 }
130 }};
131 ($mrb:ident, optional = 1) => {{
132 let mrb = $mrb;
133 unsafe {
134 let mut opt1 = std::mem::MaybeUninit::<$crate::sys::mrb_value>::uninit();
135 let argc = $crate::sys::mrb_get_args(mrb, $crate::macros::argspec::OPT1.as_ptr(), opt1.as_mut_ptr());
136 match argc {
137 1 => {
138 let opt1 = opt1.assume_init();
139 Some(opt1)
140 }
141 0 => None,
142 _ => unreachable!("mrb_get_args should have raised"),
143 }
144 }
145 }};
146 ($mrb:ident, required = 1, optional = 1) => {{
147 let mrb = $mrb;
148 unsafe {
149 let mut req1 = std::mem::MaybeUninit::<$crate::sys::mrb_value>::uninit();
150 let mut opt1 = std::mem::MaybeUninit::<$crate::sys::mrb_value>::uninit();
151 let argc = $crate::sys::mrb_get_args(
152 mrb,
153 $crate::macros::argspec::REQ1_OPT1.as_ptr(),
154 req1.as_mut_ptr(),
155 opt1.as_mut_ptr(),
156 );
157 match argc {
158 2 => {
159 let req1 = req1.assume_init();
160 let opt1 = opt1.assume_init();
161 (req1, Some(opt1))
162 }
163 1 => {
164 let req1 = req1.assume_init();
165 (req1, None)
166 }
167 _ => unreachable!("mrb_get_args should have raised"),
168 }
169 }
170 }};
171 ($mrb:ident, required = 1, optional = 2) => {{
172 let mrb = $mrb;
173 unsafe {
174 let mut req1 = std::mem::MaybeUninit::<$crate::sys::mrb_value>::uninit();
175 let mut opt1 = std::mem::MaybeUninit::<$crate::sys::mrb_value>::uninit();
176 let mut opt2 = std::mem::MaybeUninit::<$crate::sys::mrb_value>::uninit();
177 let argc = $crate::sys::mrb_get_args(
178 mrb,
179 $crate::macros::argspec::REQ1_OPT2.as_ptr(),
180 req1.as_mut_ptr(),
181 opt1.as_mut_ptr(),
182 opt2.as_mut_ptr(),
183 );
184 match argc {
185 3 => {
186 let req1 = req1.assume_init();
187 let opt1 = opt1.assume_init();
188 let opt2 = opt2.assume_init();
189 (req1, Some(opt1), Some(opt2))
190 }
191 2 => {
192 let req1 = req1.assume_init();
193 let opt1 = opt1.assume_init();
194 (req1, Some(opt1), None)
195 }
196 1 => {
197 let req1 = req1.assume_init();
198 (req1, None, None)
199 }
200 _ => unreachable!("mrb_get_args should have raised"),
201 }
202 }
203 }};
204 ($mrb:ident, required = 1, optional = 3) => {{
205 let mrb = $mrb;
206 unsafe {
207 let mut req1 = std::mem::MaybeUninit::<$crate::sys::mrb_value>::uninit();
208 let mut opt1 = std::mem::MaybeUninit::<$crate::sys::mrb_value>::uninit();
209 let mut opt2 = std::mem::MaybeUninit::<$crate::sys::mrb_value>::uninit();
210 let mut opt3 = std::mem::MaybeUninit::<$crate::sys::mrb_value>::uninit();
211 let argc = $crate::sys::mrb_get_args(
212 mrb,
213 $crate::macros::argspec::REQ1_OPT3.as_ptr(),
214 req1.as_mut_ptr(),
215 opt1.as_mut_ptr(),
216 opt2.as_mut_ptr(),
217 opt3.as_mut_ptr(),
218 );
219 match argc {
220 4 => {
221 let req1 = req1.assume_init();
222 let opt1 = opt1.assume_init();
223 let opt2 = opt2.assume_init();
224 let opt3 = opt3.assume_init();
225 (req1, Some(opt1), Some(opt2), Some(opt3))
226 }
227 3 => {
228 let req1 = req1.assume_init();
229 let opt1 = opt1.assume_init();
230 let opt2 = opt2.assume_init();
231 (req1, Some(opt1), Some(opt2), None)
232 }
233 2 => {
234 let req1 = req1.assume_init();
235 let opt1 = opt1.assume_init();
236 (req1, Some(opt1), None, None)
237 }
238 1 => {
239 let req1 = req1.assume_init();
240 (req1, None, None, None)
241 }
242 _ => unreachable!("mrb_get_args should have raised"),
243 }
244 }
245 }};
246 ($mrb:ident, required = 1, &block) => {{
247 let mrb = $mrb;
248 unsafe {
249 let mut req1 = std::mem::MaybeUninit::<$crate::sys::mrb_value>::uninit();
250 let mut block = std::mem::MaybeUninit::<$crate::sys::mrb_value>::uninit();
251 let argc = $crate::sys::mrb_get_args(
252 mrb,
253 $crate::macros::argspec::REQ1_REQBLOCK.as_ptr(),
254 req1.as_mut_ptr(),
255 block.as_mut_ptr(),
256 );
257 match argc {
258 2 | 1 => {
259 let req1 = req1.assume_init();
260 let block = block.assume_init();
261 (req1, $crate::block::Block::new(block))
262 }
263 _ => unreachable!("mrb_get_args should have raised"),
264 }
265 }
266 }};
267 ($mrb:ident, required = 1, optional = 1, &block) => {{
268 let mrb = $mrb;
269 unsafe {
270 let mut req1 = std::mem::MaybeUninit::<$crate::sys::mrb_value>::uninit();
271 let mut opt1 = std::mem::MaybeUninit::<$crate::sys::mrb_value>::uninit();
272 let mut has_opt1 = std::mem::MaybeUninit::<$crate::sys::mrb_bool>::uninit();
273 let mut block = std::mem::MaybeUninit::<$crate::sys::mrb_value>::uninit();
274 let argc = $crate::sys::mrb_get_args(
275 mrb,
276 $crate::macros::argspec::REQ1_REQBLOCK_OPT1.as_ptr(),
277 req1.as_mut_ptr(),
278 block.as_mut_ptr(),
279 opt1.as_mut_ptr(),
280 has_opt1.as_mut_ptr(),
281 );
282 let has_opt1 = has_opt1.assume_init();
283 match argc {
284 3 => {
285 let req1 = req1.assume_init();
286 let opt1 = opt1.assume_init();
287 let block = block.assume_init();
288 (req1, Some(opt1), $crate::block::Block::new(block))
289 }
290 2 => {
291 let req1 = req1.assume_init();
292 let opt1 = if has_opt1 { Some(opt1.assume_init()) } else { None };
293 let block = block.assume_init();
294 (req1, opt1, $crate::block::Block::new(block))
295 }
296 1 => {
297 let req1 = req1.assume_init();
298 let block = block.assume_init();
299 (req1, None, $crate::block::Block::new(block))
300 }
301 _ => unreachable!("mrb_get_args should have raised"),
302 }
303 }
304 }};
305 ($mrb:ident, required = 1, optional = 2, &block) => {{
306 let mrb = $mrb;
307 unsafe {
308 let mut req1 = std::mem::MaybeUninit::<$crate::sys::mrb_value>::uninit();
309 let mut opt1 = std::mem::MaybeUninit::<$crate::sys::mrb_value>::uninit();
310 let mut has_opt1 = std::mem::MaybeUninit::<$crate::sys::mrb_bool>::uninit();
311 let mut opt2 = std::mem::MaybeUninit::<$crate::sys::mrb_value>::uninit();
312 let mut has_opt2 = std::mem::MaybeUninit::<$crate::sys::mrb_bool>::uninit();
313 let mut block = std::mem::MaybeUninit::<$crate::sys::mrb_value>::uninit();
314 let argc = $crate::sys::mrb_get_args(
315 mrb,
316 $crate::macros::argspec::REQ1_REQBLOCK_OPT2.as_ptr(),
317 req1.as_mut_ptr(),
318 block.as_mut_ptr(),
319 opt1.as_mut_ptr(),
320 has_opt1.as_mut_ptr(),
321 opt2.as_mut_ptr(),
322 has_opt2.as_mut_ptr(),
323 );
324 let has_opt1 = has_opt1.assume_init();
325 let has_opt2 = has_opt2.assume_init();
326 match argc {
327 4 => {
328 let req1 = req1.assume_init();
329 let opt1 = if has_opt1 { Some(opt1.assume_init()) } else { None };
330 let opt2 = if has_opt2 { Some(opt2.assume_init()) } else { None };
331 let block = block.assume_init();
332 (req1, opt1, opt2, $crate::block::Block::new(block))
333 }
334 3 => {
335 let req1 = req1.assume_init();
336 let opt1 = if has_opt1 { Some(opt1.assume_init()) } else { None };
337 let opt2 = if has_opt2 { Some(opt2.assume_init()) } else { None };
338 let block = block.assume_init();
339 (req1, opt1, opt2, $crate::block::Block::new(block))
340 }
341 2 => {
342 let req1 = req1.assume_init();
343 let opt1 = if has_opt1 { Some(opt1.assume_init()) } else { None };
344 let block = block.assume_init();
345 (req1, opt1, None, $crate::block::Block::new(block))
346 }
347 1 => {
348 let req1 = req1.assume_init();
349 let block = block.assume_init();
350 (req1, None, None, $crate::block::Block::new(block))
351 }
352 _ => unreachable!("mrb_get_args should have raised"),
353 }
354 }
355 }};
356 ($mrb:ident, required = 2) => {{
357 let mrb = $mrb;
358 unsafe {
359 let mut req1 = std::mem::MaybeUninit::<$crate::sys::mrb_value>::uninit();
360 let mut req2 = std::mem::MaybeUninit::<$crate::sys::mrb_value>::uninit();
361 let argc = $crate::sys::mrb_get_args(
362 mrb,
363 $crate::macros::argspec::REQ2.as_ptr(),
364 req1.as_mut_ptr(),
365 req2.as_mut_ptr(),
366 );
367 match argc {
368 2 => {
369 let req1 = req1.assume_init();
370 let req2 = req2.assume_init();
371 (req1, req2)
372 }
373 _ => unreachable!("mrb_get_args should have raised"),
374 }
375 }
376 }};
377 ($mrb:ident, optional = 2) => {{
378 let mrb = $mrb;
379 unsafe {
380 let mut opt1 = std::mem::MaybeUninit::<$crate::sys::mrb_value>::uninit();
381 let mut opt2 = std::mem::MaybeUninit::<$crate::sys::mrb_value>::uninit();
382 let argc = $crate::sys::mrb_get_args(
383 mrb,
384 $crate::macros::argspec::OPT2.as_ptr(),
385 opt1.as_mut_ptr(),
386 opt2.as_mut_ptr(),
387 );
388 match argc {
389 2 => {
390 let opt1 = opt1.assume_init();
391 let opt2 = opt2.assume_init();
392 (Some(opt1), Some(opt2))
393 }
394 1 => {
395 let opt1 = opt1.assume_init();
396 (Some(opt1), None)
397 }
398 0 => (None, None),
399 _ => unreachable!("mrb_get_args should have raised"),
400 }
401 }
402 }};
403 ($mrb:ident, optional = 2, &block) => {{
404 let mrb = $mrb;
405 unsafe {
406 let mut opt1 = std::mem::MaybeUninit::<$crate::sys::mrb_value>::uninit();
407 let mut has_opt1 = std::mem::MaybeUninit::<$crate::sys::mrb_bool>::uninit();
408 let mut opt2 = std::mem::MaybeUninit::<$crate::sys::mrb_value>::uninit();
409 let mut has_opt2 = std::mem::MaybeUninit::<$crate::sys::mrb_bool>::uninit();
410 let mut block = std::mem::MaybeUninit::<$crate::sys::mrb_value>::uninit();
411 $crate::sys::mrb_get_args(
412 mrb,
413 $crate::macros::argspec::OPT2_OPTBLOCK.as_ptr(),
414 block.as_mut_ptr(),
415 opt1.as_mut_ptr(),
416 has_opt1.as_mut_ptr(),
417 opt2.as_mut_ptr(),
418 has_opt2.as_mut_ptr(),
419 );
420 let has_opt1 = has_opt1.assume_init();
421 let has_opt2 = has_opt2.assume_init();
422 let opt1 = if has_opt1 { Some(opt1.assume_init()) } else { None };
423 let opt2 = if has_opt2 { Some(opt2.assume_init()) } else { None };
424 let block = block.assume_init();
425 (opt1, opt2, $crate::block::Block::new(block))
426 }
427 }};
428 ($mrb:ident, required = 2, optional = 1) => {{
429 let mrb = $mrb;
430 unsafe {
431 let mut req1 = std::mem::MaybeUninit::<$crate::sys::mrb_value>::uninit();
432 let mut req2 = std::mem::MaybeUninit::<$crate::sys::mrb_value>::uninit();
433 let mut opt1 = std::mem::MaybeUninit::<$crate::sys::mrb_value>::uninit();
434 let argc = $crate::sys::mrb_get_args(
435 mrb,
436 $crate::macros::argspec::REQ2_OPT1.as_ptr(),
437 req1.as_mut_ptr(),
438 req2.as_mut_ptr(),
439 opt1.as_mut_ptr(),
440 );
441 match argc {
442 3 => {
443 let req1 = req1.assume_init();
444 let req2 = req2.assume_init();
445 let opt1 = opt1.assume_init();
446 (req1, req2, Some(opt1))
447 }
448 2 => {
449 let req1 = req1.assume_init();
450 let req2 = req2.assume_init();
451 (req1, req2, None)
452 }
453 _ => unreachable!("mrb_get_args should have raised"),
454 }
455 }
456 }};
457 ($mrb:ident, *args) => {{
458 let mrb = $mrb;
459 unsafe {
460 let mut args = std::mem::MaybeUninit::<*const $crate::sys::mrb_value>::uninit();
461 let mut count = std::mem::MaybeUninit::<usize>::uninit();
462 let _argc = $crate::sys::mrb_get_args(
463 mrb,
464 $crate::macros::argspec::REST.as_ptr(),
465 args.as_mut_ptr(),
466 count.as_mut_ptr(),
467 );
468 let args = args.assume_init();
469 let count = count.assume_init();
470 if args.is_null() || count == 0 {
471 &[]
472 } else {
473 std::slice::from_raw_parts(args, count)
474 }
475 }
476 }};
477}