@@ -27,6 +27,14 @@ struct Node {
2727 fields : Option < Vec < NodeField > > ,
2828}
2929
30+ impl Node {
31+ fn variant_name ( & self ) -> & str {
32+ self . rust_name
33+ . strip_suffix ( "Node" )
34+ . unwrap_or ( & self . rust_name )
35+ }
36+ }
37+
3038fn main ( ) -> Result < ( ) , Box < dyn Error > > {
3139 let config_path = Path :: new ( env ! ( "CARGO_MANIFEST_DIR" ) )
3240 . join ( "../../config.yml" )
@@ -62,11 +70,12 @@ fn main() -> Result<(), Box<dyn Error>> {
6270enum CIdentifier {
6371 Type , // foo_bar_t
6472 Constant , // FOO_BAR
73+ Method , // visit_foo_bar
6574}
6675
6776fn convert_name ( name : & str , identifier : CIdentifier ) -> String {
6877 let type_name = name. replace ( "::" , "_" ) ;
69- let lowercase = matches ! ( identifier, CIdentifier :: Type ) ;
78+ let lowercase = matches ! ( identifier, CIdentifier :: Type | CIdentifier :: Method ) ;
7079 let mut out = String :: new ( ) ;
7180 let mut prev_is_lower = false ;
7281
@@ -94,12 +103,67 @@ fn convert_name(name: &str, identifier: CIdentifier) -> String {
94103 }
95104 }
96105
97- if lowercase {
106+ if matches ! ( identifier , CIdentifier :: Type ) {
98107 out. push_str ( "_t" ) ;
99108 }
100109 out
101110}
102111
112+ fn write_visit_trait ( file : & mut File , config : & Config ) -> Result < ( ) , Box < dyn std:: error:: Error > > {
113+ writeln ! ( file, "/// A trait for visiting the AST." ) ?;
114+ writeln ! ( file, "pub trait Visit {{" ) ?;
115+ writeln ! ( file, " /// Visits a node." ) ?;
116+ writeln ! ( file, " fn visit(&mut self, node: &Node) {{" ) ?;
117+ writeln ! ( file, " match node {{" ) ?;
118+
119+ for node in & config. nodes {
120+ writeln ! ( file, " Node::{}(it) => {{" , node. variant_name( ) ) ?;
121+ writeln ! (
122+ file,
123+ " self.visit_{}_node(it);" ,
124+ convert_name( & node. variant_name( ) , CIdentifier :: Method )
125+ ) ?;
126+ writeln ! ( file, " }}" ) ?;
127+ }
128+
129+ writeln ! ( file, " }}" ) ?;
130+ writeln ! ( file, " }}" ) ?;
131+
132+ for node in & config. nodes {
133+ writeln ! ( file) ?;
134+ writeln ! ( file, " /// Visits a `{}` node." , node. name) ?;
135+ writeln ! (
136+ file,
137+ " fn visit_{}_node(&mut self, node: &{}Node) {{" ,
138+ convert_name( & node. variant_name( ) , CIdentifier :: Method ) ,
139+ node. variant_name( )
140+ ) ?;
141+ writeln ! (
142+ file,
143+ " visit_{}_node(self, node);" ,
144+ convert_name( & node. variant_name( ) , CIdentifier :: Method )
145+ ) ?;
146+ writeln ! ( file, " }}" ) ?;
147+ }
148+ writeln ! ( file, "}}" ) ?;
149+ writeln ! ( file) ?;
150+
151+ for node in & config. nodes {
152+ writeln ! ( file, "#[allow(unused_variables)]" ) ?; // TODO: Remove this once all nodes that need visitor are implemented
153+ writeln ! (
154+ file,
155+ "pub fn visit_{}_node<V: Visit + ?Sized>(visitor: &mut V, node: &{}Node) {{" ,
156+ convert_name( & node. variant_name( ) , CIdentifier :: Method ) ,
157+ node. variant_name( )
158+ ) ?;
159+ // TODO: Implement the default implementation of public visits
160+ writeln ! ( file, "}}" ) ?;
161+ writeln ! ( file) ?;
162+ }
163+
164+ Ok ( ( ) )
165+ }
166+
103167fn generate ( config : & Config ) -> Result < ( ) , Box < dyn Error > > {
104168 let out_dir = env:: var ( "OUT_DIR" ) ?;
105169 let dest_path = Path :: new ( & out_dir) . join ( "bindings.rs" ) ;
@@ -291,18 +355,13 @@ fn generate(config: &Config) -> Result<(), Box<dyn Error>> {
291355 ) ?;
292356 writeln ! ( file, " match unsafe {{ (*node).type_ }} {{" ) ?;
293357 for node in & config. nodes {
294- let variant_name = node
295- . rust_name
296- . strip_suffix ( "Node" )
297- . unwrap_or ( & node. rust_name ) ;
298-
299358 let enum_name = convert_name ( & node. name , CIdentifier :: Constant ) ;
300359
301360 writeln ! (
302361 file,
303362 " rbs_node_type::{} => Self::{}({} {{ parser, pointer: node.cast::<{}>() }})," ,
304363 enum_name,
305- variant_name,
364+ node . variant_name( ) ,
306365 node. rust_name,
307366 convert_name( & node. name, CIdentifier :: Type )
308367 ) ?;
@@ -314,6 +373,9 @@ fn generate(config: &Config) -> Result<(), Box<dyn Error>> {
314373 writeln ! ( file, " }}" ) ?;
315374 writeln ! ( file, " }}" ) ?;
316375 writeln ! ( file, "}}" ) ?;
376+ writeln ! ( file) ?;
377+
378+ write_visit_trait ( & mut file, config) ?;
317379
318380 Ok ( ( ) )
319381}
0 commit comments