Skip to content

Commit d8f8407

Browse files
committed
Add StateMachineNames
1 parent ef42361 commit d8f8407

3 files changed

Lines changed: 39 additions & 16 deletions

File tree

libcc2rs-macros/src/goto.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,16 @@
22
// Distributed under the MIT license that can be found in the LICENSE file.
33

44
use proc_macro::TokenStream;
5+
use proc_macro2::Span;
56
use syn::parse::{Parse, ParseStream};
6-
use syn::{Expr, Lifetime, Token, parse_macro_input};
7+
use syn::{Block, Expr, ExprBlock, Lifetime, Stmt, parse_macro_input};
78

8-
use crate::state_machine::{Arm, GotoStateMachine, StateMachine};
9+
use crate::state_machine::{Arm, GotoStateMachine, StateMachineNames, StateMachine};
910

1011
pub fn expand(input: TokenStream) -> TokenStream {
1112
let GotoBlockInput { arms } = parse_macro_input!(input as GotoBlockInput);
1213
GotoStateMachine {
14+
names: StateMachineNames::fresh(),
1315
arms: arms
1416
.into_iter()
1517
.map(|a| Arm {

libcc2rs-macros/src/state_machine.rs

Lines changed: 28 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
11
// Copyright (c) 2022-present INESC-ID.
22
// Distributed under the MIT license that can be found in the LICENSE file.
33

4+
use std::collections::HashMap;
5+
use std::sync::atomic::{AtomicU64, Ordering};
6+
47
use proc_macro2::{Ident, Span, TokenStream as TokenStream2};
58
use quote::{format_ident, quote};
69
use syn::visit_mut::{self, VisitMut};
7-
use syn::{Expr, ExprBreak, ExprContinue, Lifetime, Pat};
10+
use syn::{Expr, ExprBreak, ExprContinue, Lifetime, Pat, Stmt, parse_quote};
811

912
pub struct Arm {
1013
pub label: String,
@@ -21,12 +24,29 @@ pub trait StateMachine {
2124
fn emit(self) -> TokenStream2;
2225
}
2326

24-
fn sm_label() -> Lifetime {
25-
Lifetime::new("'__sm", Span::call_site())
27+
pub(crate) struct StateMachineNames {
28+
pub label: Lifetime,
29+
pub state: Ident,
30+
pub break_flag: Ident,
31+
pub cont_flag: Ident,
32+
}
33+
34+
impl StateMachineNames {
35+
pub fn fresh() -> Self {
36+
static COUNTER: AtomicU64 = AtomicU64::new(0);
37+
let id = COUNTER.fetch_add(1, Ordering::Relaxed);
38+
Self {
39+
label: Lifetime::new(&format!("'__sm{id}"), Span::call_site()),
40+
state: format_ident!("__s{}", id),
41+
break_flag: format_ident!("__user_break{}", id),
42+
cont_flag: format_ident!("__user_continue{}", id),
43+
}
44+
}
2645
}
2746

2847
// Collection of labeled arms that fall-through by default
2948
pub struct GotoStateMachine {
49+
pub names: StateMachineNames,
3050
pub arms: Vec<Arm>,
3151
}
3252

@@ -87,10 +107,7 @@ impl GotoStateMachine {
87107

88108
impl StateMachine for GotoStateMachine {
89109
fn emit(self) -> TokenStream2 {
90-
let lbl = sm_label();
91-
let s = format_ident!("__s");
92-
let break_flag = format_ident!("__user_break");
93-
let cont_flag = format_ident!("__user_continue");
110+
let StateMachineNames { label: lbl, state: s, break_flag, cont_flag } = self.names;
94111

95112
let n = self.arms.len();
96113
let mut arms_have_break = false;
@@ -186,17 +203,16 @@ impl SwitchStateMachine {
186203

187204
impl StateMachine for SwitchStateMachine {
188205
fn emit(self) -> TokenStream2 {
189-
let lbl = sm_label();
190-
let s = format_ident!("__s");
206+
let names = StateMachineNames::fresh();
191207

192-
let user_arms = Self::convert_break_to_switch_exit(&self.goto.arms, &lbl);
193-
let dispatch = self.build_dispatch_arm(&user_arms, &lbl, &s);
208+
let user_arms = Self::convert_break_to_switch_exit(&self.goto.arms, &names.label);
209+
let dispatch = self.build_dispatch_arm(&user_arms, &names.label, &names.state);
194210

195211
let mut arms = Vec::new();
196212
arms.push(dispatch);
197213
arms.extend(user_arms);
198214

199-
GotoStateMachine { arms }.emit()
215+
GotoStateMachine { names, arms }.emit()
200216
}
201217
}
202218

libcc2rs-macros/src/switch.rs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,9 @@ use proc_macro::TokenStream;
55
use syn::parse::{Parse, ParseStream};
66
use syn::{Expr, Pat, parse_macro_input};
77

8-
use crate::state_machine::{Arm, DispatchCase, GotoStateMachine, StateMachine, SwitchStateMachine};
8+
use crate::state_machine::{
9+
Arm, DispatchCase, GotoStateMachine, StateMachineNames, StateMachine, SwitchStateMachine,
10+
};
911

1012
pub fn expand(input: TokenStream) -> TokenStream {
1113
let SwitchInput { condition, arms } = parse_macro_input!(input as SwitchInput);
@@ -24,7 +26,10 @@ pub fn expand(input: TokenStream) -> TokenStream {
2426
});
2527
}
2628
SwitchStateMachine {
27-
goto: GotoStateMachine { arms: cfg_arms },
29+
goto: GotoStateMachine {
30+
names: StateMachineNames::fresh(),
31+
arms: cfg_arms,
32+
},
2833
condition,
2934
cases,
3035
}

0 commit comments

Comments
 (0)