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+
47use proc_macro2:: { Ident , Span , TokenStream as TokenStream2 } ;
58use quote:: { format_ident, quote} ;
69use 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
912pub 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
2948pub struct GotoStateMachine {
49+ pub names : StateMachineNames ,
3050 pub arms : Vec < Arm > ,
3151}
3252
@@ -87,10 +107,7 @@ impl GotoStateMachine {
87107
88108impl 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
187204impl 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
0 commit comments