Skip to content

Commit 5d79480

Browse files
committed
Generate child node traversal in visitor functions
1 parent 2b0936c commit 5d79480

1 file changed

Lines changed: 98 additions & 0 deletions

File tree

rust/ruby-rbs/build.rs

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,19 @@ fn write_visit_trait(file: &mut File, config: &Config) -> Result<(), Box<dyn std
185185
writeln!(file, "}}")?;
186186
writeln!(file)?;
187187

188+
// Map C field types (e.g. `rbs_type_name`) to the corresponding
189+
// visitor method name (e.g. `type_name` -> `visit_type_name_node`).
190+
let visitor_method_names: std::collections::HashMap<String, String> = config
191+
.nodes
192+
.iter()
193+
.map(|node| {
194+
let c_type = convert_name(&node.name, CIdentifier::Type);
195+
let c_type = c_type.strip_suffix("_t").unwrap_or(&c_type).to_string();
196+
let method = convert_name(node.variant_name(), CIdentifier::Method);
197+
(c_type, method)
198+
})
199+
.collect();
200+
188201
for node in &config.nodes {
189202
let node_variant_name = node.variant_name();
190203
let method_name = convert_name(node_variant_name, CIdentifier::Method);
@@ -195,6 +208,91 @@ fn write_visit_trait(file: &mut File, config: &Config) -> Result<(), Box<dyn std
195208
"pub fn visit_{}_node<V: Visit + ?Sized>(visitor: &mut V, node: &{}Node) {{",
196209
method_name, node_variant_name
197210
)?;
211+
212+
if let Some(fields) = &node.fields {
213+
for field in fields {
214+
let field_method_name = if field.name == "type" {
215+
"type_"
216+
} else {
217+
field.name.as_str()
218+
};
219+
220+
match field.c_type.as_str() {
221+
"rbs_node" => {
222+
if field.optional {
223+
writeln!(
224+
file,
225+
" if let Some(item) = node.{field_method_name}() {{"
226+
)?;
227+
writeln!(file, " visitor.visit(&item);")?;
228+
writeln!(file, " }}")?;
229+
} else {
230+
writeln!(file, " visitor.visit(&node.{field_method_name}());")?;
231+
}
232+
}
233+
234+
"rbs_node_list" => {
235+
if field.optional {
236+
writeln!(
237+
file,
238+
" if let Some(list) = node.{field_method_name}() {{"
239+
)?;
240+
writeln!(file, " for item in list.iter() {{")?;
241+
writeln!(file, " visitor.visit(&item);")?;
242+
writeln!(file, " }}")?;
243+
writeln!(file, " }}")?;
244+
} else {
245+
writeln!(file, " for item in node.{field_method_name}().iter() {{")?;
246+
writeln!(file, " visitor.visit(&item);")?;
247+
writeln!(file, " }}")?;
248+
}
249+
}
250+
251+
"rbs_hash" => {
252+
if field.optional {
253+
writeln!(
254+
file,
255+
" if let Some(hash) = node.{field_method_name}() {{"
256+
)?;
257+
writeln!(file, " for (key, value) in hash.iter() {{")?;
258+
writeln!(file, " visitor.visit(&key);")?;
259+
writeln!(file, " visitor.visit(&value);")?;
260+
writeln!(file, " }}")?;
261+
writeln!(file, " }}")?;
262+
} else {
263+
writeln!(
264+
file,
265+
" for (key, value) in node.{field_method_name}().iter() {{"
266+
)?;
267+
writeln!(file, " visitor.visit(&key);")?;
268+
writeln!(file, " visitor.visit(&value);")?;
269+
writeln!(file, " }}")?;
270+
}
271+
}
272+
273+
_ => {
274+
if let Some(visit_method_name) = visitor_method_names.get(&field.c_type) {
275+
if field.optional {
276+
writeln!(
277+
file,
278+
" if let Some(item) = node.{field_method_name}() {{"
279+
)?;
280+
writeln!(
281+
file,
282+
" visitor.visit_{visit_method_name}_node(&item);"
283+
)?;
284+
writeln!(file, " }}")?;
285+
} else {
286+
writeln!(
287+
file,
288+
" visitor.visit_{visit_method_name}_node(&node.{field_method_name}());"
289+
)?;
290+
}
291+
}
292+
}
293+
}
294+
}
295+
}
198296
writeln!(file, "}}")?;
199297
writeln!(file)?;
200298
}

0 commit comments

Comments
 (0)