Skip to content

Commit 6841807

Browse files
authored
Merge pull request #136 from eddyb/variants
generate: track the newtype/struct-like variant distinction in RustAdt.
2 parents 5b28af9 + a879ed5 commit 6841807

File tree

1 file changed

+76
-55
lines changed

1 file changed

+76
-55
lines changed

src/generate/rust.rs

Lines changed: 76 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -94,9 +94,17 @@ struct RustField {
9494
paths: Vec<Vec<usize>>,
9595
}
9696

97+
enum RustVariant {
98+
// `Foo:X`, the whole top-level field is wrapped `Foo(X)`.
99+
Newtype(RustField),
100+
101+
// `Bar:{ x:X y:Y }`, subfields are extracted into `Bar { x: X, y: Y }`.
102+
StructLike(IndexMap<IStr, RustField>),
103+
}
104+
97105
enum RustAdt {
98106
Struct(IndexMap<IStr, RustField>),
99-
Enum(IndexMap<IStr, (IRule, IndexMap<IStr, RustField>)>),
107+
Enum(IndexMap<IStr, (IRule, RustVariant)>),
100108
}
101109

102110
trait RuleWithFieldsMethods<Pat> {
@@ -198,11 +206,17 @@ impl<Pat: RustInputPat> RuleWithFieldsMethods<Pat> for RuleWithFields {
198206
.enumerate()
199207
.map(|(i, &rule)| match cx[children[i]] {
200208
Fields::Leaf(Some(field)) => {
201-
let child = RuleWithFields {
209+
let subfields = RuleWithFields {
202210
rule,
203211
fields: field.sub,
212+
}
213+
.rust_fields(cx);
214+
let variant = if subfields.is_empty() {
215+
RustVariant::Newtype(rule.leaf_rust_field(cx))
216+
} else {
217+
RustVariant::StructLike(subfields)
204218
};
205-
Some((field.name, (rule, child.rust_fields(cx))))
219+
Some((field.name, (rule, variant)))
206220
}
207221
_ => None,
208222
})
@@ -973,18 +987,20 @@ where
973987

974988
let rule_ty_def = match &rust_adt {
975989
RustAdt::Enum(variants) => {
976-
let variants = variants.iter().map(|(&v_name, (v_rule, v_fields))| {
990+
let variants = variants.iter().map(|(&v_name, (_, variant))| {
977991
let variant_ident = Src::ident(&cx[v_name]);
978-
if v_fields.is_empty() {
979-
// FIXME(eddyb) this should be reflected in `RustAdt`
980-
let field_ty = field_handle_ty(&v_rule.leaf_rust_field(cx));
981-
quote!(#variant_ident(#field_ty))
982-
} else {
983-
let fields_ident = v_fields.keys().map(|&name| Src::ident(&cx[name]));
984-
let fields_ty = v_fields.values().map(field_handle_ty);
985-
quote!(#variant_ident {
986-
#(#fields_ident: #fields_ty),*
987-
})
992+
match variant {
993+
RustVariant::Newtype(field) => {
994+
let field_ty = field_handle_ty(field);
995+
quote!(#variant_ident(#field_ty))
996+
}
997+
RustVariant::StructLike(v_fields) => {
998+
let fields_ident = v_fields.keys().map(|&name| Src::ident(&cx[name]));
999+
let fields_ty = v_fields.values().map(field_handle_ty);
1000+
quote!(#variant_ident {
1001+
#(#fields_ident: #fields_ty),*
1002+
})
1003+
}
9881004
}
9891005
});
9901006
quote!(
@@ -1063,20 +1079,21 @@ where
10631079
let variants_from_forest_ident = variants
10641080
.keys()
10651081
.map(|&v_name| Src::ident(format!("{}_from_forest", &cx[v_name])));
1066-
let variants_body = variants.iter().map(|(&v_name, (_, v_fields))| {
1082+
let variants_body = variants.iter().map(|(&v_name, (_, variant))| {
10671083
let variant_ident = Src::ident(&cx[v_name]);
1068-
if v_fields.is_empty() {
1069-
quote!(#ident::#variant_ident(Handle {
1084+
match variant {
1085+
RustVariant::Newtype(_) => quote!(#ident::#variant_ident(Handle {
10701086
node: _node,
10711087
forest,
10721088
_marker: PhantomData,
1073-
}))
1074-
} else {
1075-
let fields_ident = v_fields.keys().map(|&name| Src::ident(&cx[name]));
1076-
let fields_expr = v_fields.values().map(field_handle_expr);
1077-
quote!(#ident::#variant_ident {
1078-
#(#fields_ident: #fields_expr),*
1079-
})
1089+
})),
1090+
RustVariant::StructLike(v_fields) => {
1091+
let fields_ident = v_fields.keys().map(|&name| Src::ident(&cx[name]));
1092+
let fields_expr = v_fields.values().map(field_handle_expr);
1093+
quote!(#ident::#variant_ident {
1094+
#(#fields_ident: #fields_expr),*
1095+
})
1096+
}
10801097
}
10811098
});
10821099

@@ -1239,42 +1256,46 @@ fn rule_debug_impl<Pat>(cx: &Context<Pat>, name: IStr, rust_adt: &RustAdt) -> Sr
12391256
let ident = Src::ident(name);
12401257
let body = match rust_adt {
12411258
RustAdt::Enum(variants) => {
1242-
let variants_pat = variants.iter().map(|(&v_name, (_, v_fields))| {
1259+
let variants_pat = variants.iter().map(|(&v_name, (_, variant))| {
12431260
let variant_ident = Src::ident(&cx[v_name]);
1244-
if v_fields.is_empty() {
1245-
quote!(#ident::#variant_ident(x))
1246-
} else {
1247-
let fields_ident = v_fields.keys().map(|&name| Src::ident(&cx[name]));
1248-
let fields_var_ident = v_fields
1249-
.keys()
1250-
.map(|&field_name| Src::ident(format!("f_{}", &cx[field_name])));
1251-
quote!(#ident::#variant_ident {
1252-
#(#fields_ident: #fields_var_ident,)*
1253-
})
1261+
match variant {
1262+
RustVariant::Newtype(_) => quote!(#ident::#variant_ident(x)),
1263+
RustVariant::StructLike(v_fields) => {
1264+
let fields_ident = v_fields.keys().map(|&name| Src::ident(&cx[name]));
1265+
let fields_var_ident = v_fields
1266+
.keys()
1267+
.map(|&field_name| Src::ident(format!("f_{}", &cx[field_name])));
1268+
quote!(#ident::#variant_ident {
1269+
#(#fields_ident: #fields_var_ident,)*
1270+
})
1271+
}
12541272
}
12551273
});
1256-
let variants_body = variants.iter().map(|(&v_name, (_, v_fields))| {
1274+
let variants_body = variants.iter().map(|(&v_name, (_, variant))| {
12571275
let variant_path_str = format!("{}::{}", name, &cx[v_name]);
1258-
if v_fields.is_empty() {
1259-
quote!(f.debug_tuple(#variant_path_str).field(x).finish(),)
1260-
} else {
1261-
let fields_debug = v_fields.iter().map(|(field_name, field)| {
1262-
let field_name = &cx[*field_name];
1263-
let field_var_ident = Src::ident(format!("f_{}", field_name));
1264-
if field.refutable {
1265-
quote!(if let Some(field) = #field_var_ident {
1266-
d.field(#field_name, field);
1267-
})
1268-
} else {
1269-
quote!(d.field(#field_name, #field_var_ident);)
1270-
}
1271-
});
1276+
match variant {
1277+
RustVariant::Newtype(_) => {
1278+
quote!(f.debug_tuple(#variant_path_str).field(x).finish(),)
1279+
}
1280+
RustVariant::StructLike(v_fields) => {
1281+
let fields_debug = v_fields.iter().map(|(field_name, field)| {
1282+
let field_name = &cx[*field_name];
1283+
let field_var_ident = Src::ident(format!("f_{}", field_name));
1284+
if field.refutable {
1285+
quote!(if let Some(field) = #field_var_ident {
1286+
d.field(#field_name, field);
1287+
})
1288+
} else {
1289+
quote!(d.field(#field_name, #field_var_ident);)
1290+
}
1291+
});
12721292

1273-
quote!({
1274-
let mut d = f.debug_struct(#variant_path_str);
1275-
#(#fields_debug)*
1276-
d.finish()
1277-
})
1293+
quote!({
1294+
let mut d = f.debug_struct(#variant_path_str);
1295+
#(#fields_debug)*
1296+
d.finish()
1297+
})
1298+
}
12781299
}
12791300
});
12801301

0 commit comments

Comments
 (0)