Skip to content

Commit cdf8bd0

Browse files
committed
Generate child node traversal in visitor functions
1 parent b8eeab8 commit cdf8bd0

1 file changed

Lines changed: 101 additions & 0 deletions

File tree

rust/ruby-rbs/build.rs

Lines changed: 101 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,94 @@ 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!(
246+
file,
247+
" for item in node.{field_method_name}().iter() {{"
248+
)?;
249+
writeln!(file, " visitor.visit(&item);")?;
250+
writeln!(file, " }}")?;
251+
}
252+
}
253+
254+
"rbs_hash" => {
255+
if field.optional {
256+
writeln!(
257+
file,
258+
" if let Some(hash) = node.{field_method_name}() {{"
259+
)?;
260+
writeln!(file, " for (key, value) in hash.iter() {{")?;
261+
writeln!(file, " visitor.visit(&key);")?;
262+
writeln!(file, " visitor.visit(&value);")?;
263+
writeln!(file, " }}")?;
264+
writeln!(file, " }}")?;
265+
} else {
266+
writeln!(
267+
file,
268+
" for (key, value) in node.{field_method_name}().iter() {{"
269+
)?;
270+
writeln!(file, " visitor.visit(&key);")?;
271+
writeln!(file, " visitor.visit(&value);")?;
272+
writeln!(file, " }}")?;
273+
}
274+
}
275+
276+
_ => {
277+
if let Some(visit_method_name) = visitor_method_names.get(&field.c_type) {
278+
if field.optional {
279+
writeln!(
280+
file,
281+
" if let Some(item) = node.{field_method_name}() {{"
282+
)?;
283+
writeln!(
284+
file,
285+
" visitor.visit_{visit_method_name}_node(&item);"
286+
)?;
287+
writeln!(file, " }}")?;
288+
} else {
289+
writeln!(
290+
file,
291+
" visitor.visit_{visit_method_name}_node(&node.{field_method_name}());"
292+
)?;
293+
}
294+
}
295+
}
296+
}
297+
}
298+
}
198299
writeln!(file, "}}")?;
199300
writeln!(file)?;
200301
}

0 commit comments

Comments
 (0)