Skip to content

Commit ef42361

Browse files
committed
Allow rustfmt to pretty-print inside goto_block
Make the statements inside goto_block printable, i.e. change form label => {} to label: {}
1 parent 3d1c579 commit ef42361

3 files changed

Lines changed: 216 additions & 26 deletions

File tree

libcc2rs-macros/src/goto.rs

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -33,15 +33,29 @@ struct GotoArm {
3333

3434
impl Parse for GotoBlockInput {
3535
fn parse(input: ParseStream) -> syn::Result<Self> {
36+
let block: Block = input.parse()?;
3637
let mut arms = Vec::new();
37-
while !input.is_empty() {
38-
let label: Lifetime = input.parse()?;
39-
input.parse::<Token![=>]>()?;
40-
let body: Expr = input.parse()?;
41-
arms.push(GotoArm { label, body });
42-
if input.peek(Token![,]) {
43-
input.parse::<Token![,]>()?;
44-
}
38+
for stmt in block.stmts {
39+
let Stmt::Expr(Expr::Block(eb), _) = stmt else {
40+
return Err(syn::Error::new(
41+
Span::call_site(),
42+
"goto_block! body must be a sequence of labeled blocks",
43+
));
44+
};
45+
let Some(label) = eb.label else {
46+
return Err(syn::Error::new(
47+
Span::call_site(),
48+
"goto_block! arm must be a labeled block",
49+
));
50+
};
51+
arms.push(GotoArm {
52+
label: label.name,
53+
body: Expr::Block(ExprBlock {
54+
attrs: eb.attrs,
55+
label: None,
56+
block: eb.block,
57+
}),
58+
});
4559
}
4660
Ok(Self { arms })
4761
}

libcc2rs-macros/src/lib.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,10 +36,10 @@ pub fn switch(input: TokenStream) -> TokenStream {
3636
switch::expand(input)
3737
}
3838

39-
// goto_block! {
40-
// '<label> => { /* body; may contain `break` or `continue` */ },
39+
// goto_block!({
40+
// '<label>: { /* body; may contain `break`, `continue`, or goto!('other) */ }
4141
// ...
42-
// };
42+
// });
4343
//
4444
// Expands to
4545
//

libcc2rs-macros/tests/control_flow.rs

Lines changed: 191 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -269,41 +269,217 @@ fn switch_in_loop() {
269269
#[test]
270270
fn goto_block_linear_fallthrough() {
271271
let mut v = 0;
272-
goto_block! {
273-
'a => { v += 1; },
274-
'b => { v += 10; },
275-
'c => { v += 100; },
276-
};
272+
goto_block!({
273+
'a: {
274+
v += 1;
275+
}
276+
'b: {
277+
v += 10;
278+
}
279+
'c: {
280+
v += 100;
281+
}
282+
});
277283
assert_eq!(v, 111);
278284
}
279285

280286
#[test]
281287
fn goto_block_return_from_arm() {
282288
#[allow(unreachable_code)]
283289
fn run(start: u32) -> &'static str {
284-
goto_block! {
285-
'a => { if start == 0 { return "a"; } },
286-
'b => { if start == 1 { return "b"; } },
287-
'c => { return "c"; },
288-
};
290+
goto_block!({
291+
'a: {
292+
if start == 0 {
293+
return "a";
294+
}
295+
}
296+
'b: {
297+
if start == 1 {
298+
return "b";
299+
}
300+
}
301+
'c: {
302+
return "c";
303+
}
304+
});
289305
"fallthrough"
290306
}
291307
assert_eq!(run(0), "a");
292308
assert_eq!(run(1), "b");
293309
assert_eq!(run(2), "c");
294310
}
295311

312+
#[test]
313+
fn goto_block_forward_goto_skips_block() {
314+
fn skip(n: i32) -> i32 {
315+
let mut x: i32 = 0;
316+
goto_block!({
317+
'__entry: {
318+
x = 0;
319+
if n > 0 {
320+
goto!('mid);
321+
}
322+
x += 10;
323+
}
324+
'mid: {
325+
x += 1;
326+
}
327+
});
328+
x
329+
}
330+
assert_eq!(skip(1), 1);
331+
assert_eq!(skip(-1), 11);
332+
}
333+
334+
#[test]
335+
fn goto_block_local_visible_across_label() {
336+
fn early(n: i32) -> i32 {
337+
let mut ret: i32 = 0;
338+
goto_block!({
339+
'__entry: {
340+
if n < 0 {
341+
ret = -1;
342+
goto!('out);
343+
}
344+
ret = 100;
345+
}
346+
'out: {
347+
return ret;
348+
}
349+
});
350+
#[allow(unreachable_code)]
351+
0
352+
}
353+
assert_eq!(early(-1), -1);
354+
assert_eq!(early(5), 100);
355+
}
356+
357+
#[test]
358+
fn goto_block_backward_goto_retry() {
359+
fn f() -> i32 {
360+
let mut sum: i32 = 0;
361+
let mut i: i32 = 0;
362+
goto_block!({
363+
'again: {
364+
let local: i32 = i;
365+
sum += local;
366+
i += 1;
367+
if i < 4 {
368+
goto!('again);
369+
}
370+
return sum;
371+
}
372+
});
373+
#[allow(unreachable_code)]
374+
0
375+
}
376+
assert_eq!(f(), 6);
377+
}
378+
379+
#[test]
380+
fn goto_block_multi_label_fallthrough() {
381+
fn classify(n: i32) -> i32 {
382+
let mut ret: i32 = 0;
383+
goto_block!({
384+
'__entry: {
385+
if n < 0 {
386+
goto!('error);
387+
}
388+
if n == 0 {
389+
goto!('out);
390+
}
391+
ret = n;
392+
goto!('out);
393+
}
394+
'error: {
395+
ret = -1;
396+
}
397+
'out: {
398+
return ret;
399+
}
400+
});
401+
#[allow(unreachable_code)]
402+
0
403+
}
404+
assert_eq!(classify(5), 5);
405+
assert_eq!(classify(0), 0);
406+
assert_eq!(classify(-2), -1);
407+
}
408+
409+
#[test]
410+
fn goto_block_goto_out_of_switch() {
411+
fn sm(n: i32) -> i32 {
412+
let mut ret: i32 = 0;
413+
goto_block!({
414+
'__entry: {
415+
switch!(match n {
416+
0 => {
417+
ret += 1;
418+
}
419+
1 => {
420+
ret += 10;
421+
goto!('out);
422+
}
423+
_ => {
424+
ret += 100;
425+
break;
426+
}
427+
});
428+
ret += 1000;
429+
}
430+
'out: {
431+
return ret;
432+
}
433+
});
434+
#[allow(unreachable_code)]
435+
0
436+
}
437+
assert_eq!(sm(0), 11);
438+
assert_eq!(sm(1), 10);
439+
assert_eq!(sm(9), 1100);
440+
}
441+
442+
#[test]
443+
fn goto_block_goto_out_of_nested_block() {
444+
fn f(n: i32) -> i32 {
445+
let mut ret: i32 = 0;
446+
goto_block!({
447+
'__entry: {
448+
goto_block!({
449+
'inner: {
450+
ret = 1;
451+
if n > 0 {
452+
goto!('out);
453+
}
454+
ret = 2;
455+
}
456+
});
457+
ret += 10;
458+
}
459+
'out: {
460+
return ret;
461+
}
462+
});
463+
#[allow(unreachable_code)]
464+
0
465+
}
466+
assert_eq!(f(1), 1);
467+
assert_eq!(f(-1), 12);
468+
}
469+
296470
#[test]
297471
fn goto_block_nested_loop_break_targets_inner() {
298472
let mut sum = 0;
299-
goto_block! {
300-
'entry => {
473+
goto_block!({
474+
'entry: {
301475
for i in 0..10 {
302-
if i == 3 { break; } // targets the for loop
476+
if i == 3 {
477+
break;
478+
} // targets the for loop
303479
sum += i;
304480
}
305481
sum += 100;
306-
},
307-
};
482+
}
483+
});
308484
assert_eq!(sum, 103);
309485
}

0 commit comments

Comments
 (0)