Skip to content

Commit 7e917c9

Browse files
author
Paolo Tranquilli
committed
Rust: move body skipping logic to code generation
1 parent a4788fd commit 7e917c9

File tree

4 files changed

+145
-700
lines changed

4 files changed

+145
-700
lines changed

rust/ast-generator/src/main.rs

Lines changed: 103 additions & 181 deletions
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,9 @@ fn node_src_to_schema_class(
114114
let (ty, child) = match &f.ty {
115115
FieldType::String => ("optional[string]".to_string(), false),
116116
FieldType::Predicate => ("predicate".to_string(), false),
117-
FieldType::Optional(ty) => (format!("optional[\"{}\"]", class_name(ty)), true),
117+
FieldType::Optional(ty) | FieldType::Body(ty) => {
118+
(format!("optional[\"{}\"]", class_name(ty)), true)
119+
}
118120
FieldType::List(ty) => (format!("list[\"{}\"]", class_name(ty)), true),
119121
};
120122
SchemaField {
@@ -169,6 +171,7 @@ enum FieldType {
169171
String,
170172
Predicate,
171173
Optional(String),
174+
Body(String),
172175
List(String),
173176
}
174177

@@ -177,158 +180,93 @@ struct FieldInfo {
177180
ty: FieldType,
178181
}
179182

183+
impl FieldInfo {
184+
pub fn optional(name: &str, ty: &str) -> FieldInfo {
185+
FieldInfo {
186+
name: name.to_string(),
187+
ty: FieldType::Optional(ty.to_string()),
188+
}
189+
}
190+
191+
pub fn body(name: &str, ty: &str) -> FieldInfo {
192+
FieldInfo {
193+
name: name.to_string(),
194+
ty: FieldType::Body(ty.to_string()),
195+
}
196+
}
197+
198+
pub fn string(name: &str) -> FieldInfo {
199+
FieldInfo {
200+
name: name.to_string(),
201+
ty: FieldType::String,
202+
}
203+
}
204+
205+
pub fn predicate(name: &str) -> FieldInfo {
206+
FieldInfo {
207+
name: name.to_string(),
208+
ty: FieldType::Predicate,
209+
}
210+
}
211+
212+
pub fn list(name: &str, ty: &str) -> FieldInfo {
213+
FieldInfo {
214+
name: name.to_string(),
215+
ty: FieldType::List(ty.to_string()),
216+
}
217+
}
218+
}
219+
180220
fn get_additional_fields(node: &AstNodeSrc) -> Vec<FieldInfo> {
181221
match node.name.as_str() {
182-
"Name" | "NameRef" | "Lifetime" => vec![FieldInfo {
183-
name: "text".to_string(),
184-
ty: FieldType::String,
185-
}],
186-
"Abi" => vec![FieldInfo {
187-
name: "abi_string".to_string(),
188-
ty: FieldType::String,
189-
}],
190-
"Literal" => vec![FieldInfo {
191-
name: "text_value".to_string(),
192-
ty: FieldType::String,
193-
}],
194-
"PrefixExpr" => vec![FieldInfo {
195-
name: "operator_name".to_string(),
196-
ty: FieldType::String,
197-
}],
222+
"Name" | "NameRef" | "Lifetime" => vec![FieldInfo::string("text")],
223+
"Abi" => vec![FieldInfo::string("abi_string")],
224+
"Literal" => vec![FieldInfo::string("text_value")],
225+
"PrefixExpr" => vec![FieldInfo::string("operator_name")],
198226
"BinExpr" => vec![
199-
FieldInfo {
200-
name: "lhs".to_string(),
201-
ty: FieldType::Optional("Expr".to_string()),
202-
},
203-
FieldInfo {
204-
name: "rhs".to_string(),
205-
ty: FieldType::Optional("Expr".to_string()),
206-
},
207-
FieldInfo {
208-
name: "operator_name".to_string(),
209-
ty: FieldType::String,
210-
},
227+
FieldInfo::optional("lhs", "Expr"),
228+
FieldInfo::optional("rhs", "Expr"),
229+
FieldInfo::string("operator_name"),
211230
],
212231
"IfExpr" => vec![
213-
FieldInfo {
214-
name: "then_branch".to_string(),
215-
ty: FieldType::Optional("BlockExpr".to_string()),
216-
},
217-
FieldInfo {
218-
name: "else_branch".to_string(),
219-
ty: FieldType::Optional("ElseBranch".to_string()),
220-
},
221-
FieldInfo {
222-
name: "condition".to_string(),
223-
ty: FieldType::Optional("Expr".to_string()),
224-
},
232+
FieldInfo::optional("then_branch", "BlockExpr"),
233+
FieldInfo::optional("else_branch", "ElseBranch"),
234+
FieldInfo::optional("condition", "Expr"),
225235
],
226236
"RangeExpr" => vec![
227-
FieldInfo {
228-
name: "start".to_string(),
229-
ty: FieldType::Optional("Expr".to_string()),
230-
},
231-
FieldInfo {
232-
name: "end".to_string(),
233-
ty: FieldType::Optional("Expr".to_string()),
234-
},
235-
FieldInfo {
236-
name: "operator_name".to_string(),
237-
ty: FieldType::String,
238-
},
237+
FieldInfo::optional("start", "Expr"),
238+
FieldInfo::optional("end", "Expr"),
239+
FieldInfo::string("operator_name"),
239240
],
240241
"RangePat" => vec![
241-
FieldInfo {
242-
name: "start".to_string(),
243-
ty: FieldType::Optional("Pat".to_string()),
244-
},
245-
FieldInfo {
246-
name: "end".to_string(),
247-
ty: FieldType::Optional("Pat".to_string()),
248-
},
249-
FieldInfo {
250-
name: "operator_name".to_string(),
251-
ty: FieldType::String,
252-
},
242+
FieldInfo::optional("start", "Pat"),
243+
FieldInfo::optional("end", "Pat"),
244+
FieldInfo::string("operator_name"),
253245
],
254246
"IndexExpr" => vec![
255-
FieldInfo {
256-
name: "index".to_string(),
257-
ty: FieldType::Optional("Expr".to_string()),
258-
},
259-
FieldInfo {
260-
name: "base".to_string(),
261-
ty: FieldType::Optional("Expr".to_string()),
262-
},
247+
FieldInfo::optional("index", "Expr"),
248+
FieldInfo::optional("base", "Expr"),
263249
],
264250
"Impl" => vec![
265-
FieldInfo {
266-
name: "trait_".to_string(),
267-
ty: FieldType::Optional("Type".to_string()),
268-
},
269-
FieldInfo {
270-
name: "self_ty".to_string(),
271-
ty: FieldType::Optional("Type".to_string()),
272-
},
251+
FieldInfo::optional("trait_", "Type"),
252+
FieldInfo::optional("self_ty", "Type"),
273253
],
274-
"ForExpr" => vec![FieldInfo {
275-
name: "iterable".to_string(),
276-
ty: FieldType::Optional("Expr".to_string()),
277-
}],
278-
"WhileExpr" => vec![FieldInfo {
279-
name: "condition".to_string(),
280-
ty: FieldType::Optional("Expr".to_string()),
281-
}],
282-
"MatchGuard" => vec![FieldInfo {
283-
name: "condition".to_string(),
284-
ty: FieldType::Optional("Expr".to_string()),
285-
}],
254+
"ForExpr" => vec![FieldInfo::optional("iterable", "Expr")],
255+
"WhileExpr" => vec![FieldInfo::optional("condition", "Expr")],
256+
"MatchGuard" => vec![FieldInfo::optional("condition", "Expr")],
286257
"MacroDef" => vec![
287-
FieldInfo {
288-
name: "args".to_string(),
289-
ty: FieldType::Optional("TokenTree".to_string()),
290-
},
291-
FieldInfo {
292-
name: "body".to_string(),
293-
ty: FieldType::Optional("TokenTree".to_string()),
294-
},
258+
FieldInfo::optional("args", "TokenTree"),
259+
FieldInfo::optional("body", "TokenTree"),
295260
],
296-
"FormatArgsExpr" => vec![FieldInfo {
297-
name: "args".to_string(),
298-
ty: FieldType::List("FormatArgsArg".to_string()),
299-
}],
300-
"ArgList" => vec![FieldInfo {
301-
name: "args".to_string(),
302-
ty: FieldType::List("Expr".to_string()),
303-
}],
304-
"Fn" => vec![FieldInfo {
305-
name: "body".to_string(),
306-
ty: FieldType::Optional("BlockExpr".to_string()),
307-
}],
308-
"Const" => vec![FieldInfo {
309-
name: "body".to_string(),
310-
ty: FieldType::Optional("Expr".to_string()),
311-
}],
312-
"Static" => vec![FieldInfo {
313-
name: "body".to_string(),
314-
ty: FieldType::Optional("Expr".to_string()),
315-
}],
316-
"ClosureExpr" => vec![FieldInfo {
317-
name: "body".to_string(),
318-
ty: FieldType::Optional("Expr".to_string()),
319-
}],
320-
"ArrayExpr" => vec![FieldInfo {
321-
name: "is_semicolon".to_string(),
322-
ty: FieldType::Predicate,
323-
}],
324-
"SelfParam" => vec![FieldInfo {
325-
name: "is_amp".to_string(),
326-
ty: FieldType::Predicate,
327-
}],
328-
"UseTree" => vec![FieldInfo {
329-
name: "is_star".to_string(),
330-
ty: FieldType::Predicate,
331-
}],
261+
"FormatArgsExpr" => vec![FieldInfo::list("args", "FormatArgsArg")],
262+
"ArgList" => vec![FieldInfo::list("args", "Expr")],
263+
"Fn" => vec![FieldInfo::body("body", "BlockExpr")],
264+
"Const" => vec![FieldInfo::body("body", "Expr")],
265+
"Static" => vec![FieldInfo::body("body", "Expr")],
266+
"ClosureExpr" => vec![FieldInfo::optional("body", "Expr")],
267+
"ArrayExpr" => vec![FieldInfo::predicate("is_semicolon")],
268+
"SelfParam" => vec![FieldInfo::predicate("is_amp")],
269+
"UseTree" => vec![FieldInfo::predicate("is_star")],
332270
_ => vec![],
333271
}
334272
}
@@ -356,6 +294,10 @@ fn get_fields(node: &AstNodeSrc) -> Vec<FieldInfo> {
356294
("ArrayExpr", "expr") // The ArrayExpr type also has an 'exprs' field
357295
| ("PathSegment", "ty" | "path_type") // these are broken, handling them manually
358296
=> continue,
297+
("Param", "pat") => {
298+
result.push(FieldInfo::body("pat", "Pat"));
299+
continue;
300+
},
359301
_ => {}
360302
}
361303
let ty = match field {
@@ -374,54 +316,26 @@ fn get_fields(node: &AstNodeSrc) -> Vec<FieldInfo> {
374316
}
375317
for trait_ in &node.traits {
376318
match trait_.as_str() {
377-
"HasAttrs" => result.push(FieldInfo {
378-
name: "attrs".to_owned(),
379-
ty: FieldType::List("Attr".to_owned()),
380-
}),
381-
"HasName" => result.push(FieldInfo {
382-
name: "name".to_owned(),
383-
ty: FieldType::Optional("Name".to_owned()),
384-
}),
385-
"HasVisibility" => result.push(FieldInfo {
386-
name: "visibility".to_owned(),
387-
ty: FieldType::Optional("Visibility".to_owned()),
388-
}),
319+
"HasAttrs" => result.push(FieldInfo::list("attrs", "Attr")),
320+
"HasName" => result.push(FieldInfo::optional("name", "Name")),
321+
"HasVisibility" => result.push(FieldInfo::optional("visibility", "Visibility")),
389322
"HasGenericParams" => {
390-
result.push(FieldInfo {
391-
name: "generic_param_list".to_owned(),
392-
ty: FieldType::Optional("GenericParamList".to_owned()),
393-
});
394-
result.push(FieldInfo {
395-
name: "where_clause".to_owned(),
396-
ty: FieldType::Optional("WhereClause".to_owned()),
397-
})
323+
result.push(FieldInfo::optional(
324+
"generic_param_list",
325+
"GenericParamList",
326+
));
327+
result.push(FieldInfo::optional("where_clause", "WhereClause"))
328+
}
329+
"HasGenericArgs" => {
330+
result.push(FieldInfo::optional("generic_arg_list", "GenericArgList"))
398331
}
399-
"HasGenericArgs" => result.push(FieldInfo {
400-
name: "generic_arg_list".to_owned(),
401-
ty: FieldType::Optional("GenericArgList".to_owned()),
402-
}),
403-
"HasTypeBounds" => result.push(FieldInfo {
404-
name: "type_bound_list".to_owned(),
405-
ty: FieldType::Optional("TypeBoundList".to_owned()),
406-
}),
407-
"HasModuleItem" => result.push(FieldInfo {
408-
name: "items".to_owned(),
409-
ty: FieldType::List("Item".to_owned()),
410-
}),
332+
"HasTypeBounds" => result.push(FieldInfo::optional("type_bound_list", "TypeBoundList")),
333+
"HasModuleItem" => result.push(FieldInfo::list("items", "Item")),
411334
"HasLoopBody" => {
412-
result.push(FieldInfo {
413-
name: "label".to_owned(),
414-
ty: FieldType::Optional("Label".to_owned()),
415-
});
416-
result.push(FieldInfo {
417-
name: "loop_body".to_owned(),
418-
ty: FieldType::Optional("BlockExpr".to_owned()),
419-
})
335+
result.push(FieldInfo::optional("label", "Label"));
336+
result.push(FieldInfo::optional("loop_body", "BlockExpr"))
420337
}
421-
"HasArgList" => result.push(FieldInfo {
422-
name: "arg_list".to_owned(),
423-
ty: FieldType::Optional("ArgList".to_owned()),
424-
}),
338+
"HasArgList" => result.push(FieldInfo::optional("arg_list", "ArgList")),
425339
"HasDocComments" => {}
426340

427341
_ => panic!("Unknown trait {}", trait_),
@@ -455,6 +369,7 @@ struct ExtractorNodeFieldInfo {
455369
predicate: bool,
456370
optional: bool,
457371
list: bool,
372+
body: bool,
458373
}
459374

460375
#[derive(Serialize)]
@@ -518,6 +433,13 @@ fn field_info_to_extractor_info(name: &str, field: &FieldInfo) -> ExtractorNodeF
518433
optional: true,
519434
..Default::default()
520435
},
436+
FieldType::Body(ty) => ExtractorNodeFieldInfo {
437+
name,
438+
method: field.name.clone(),
439+
snake_case_ty: to_lower_snake_case(ty),
440+
body: true,
441+
..Default::default()
442+
},
521443
FieldType::List(ty) => ExtractorNodeFieldInfo {
522444
name,
523445
method: field.name.clone(),

rust/ast-generator/templates/extractor.mustache

Lines changed: 18 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -34,23 +34,27 @@ impl Translator<'_> {
3434
{{#nodes}}
3535

3636
pub(crate) fn emit_{{snake_case_name}}(&mut self, node: &ast::{{ast_name}}) -> Option<Label<generated::{{name}}>> {
37-
if self.should_be_excluded(node) { return None; }
3837
{{#has_attrs}}
39-
if self.should_be_excluded_attrs(node) { return None; }
38+
if self.should_be_excluded(node) { return None; }
4039
{{/has_attrs}}
4140
{{#fields}}
42-
{{#predicate}}
43-
let {{name}} = node.{{method}}().is_some();
44-
{{/predicate}}
45-
{{#string}}
46-
let {{name}} = node.try_get_text();
47-
{{/string}}
48-
{{#list}}
49-
let {{name}} = node.{{method}}().filter_map(|x| self.emit_{{snake_case_ty}}(&x)).collect();
50-
{{/list}}
51-
{{#optional}}
52-
let {{name}} = node.{{method}}().and_then(|x| self.emit_{{snake_case_ty}}(&x));
53-
{{/optional}}
41+
let {{name}} =
42+
{{#predicate}}
43+
node.{{method}}().is_some()
44+
{{/predicate}}
45+
{{#string}}
46+
node.try_get_text()
47+
{{/string}}
48+
{{#list}}
49+
node.{{method}}().filter_map(|x| self.emit_{{snake_case_ty}}(&x)).collect()
50+
{{/list}}
51+
{{#optional}}
52+
node.{{method}}().and_then(|x| self.emit_{{snake_case_ty}}(&x))
53+
{{/optional}}
54+
{{#body}}
55+
if self.should_skip_bodies() { None } else { node.{{method}}().and_then(|x| self.emit_{{snake_case_ty}}(&x)) }
56+
{{/body}}
57+
;
5458
{{/fields}}
5559
let label = self.trap.emit(generated::{{name}} {
5660
id: TrapId::Star,

0 commit comments

Comments
 (0)