@@ -94,9 +94,17 @@ struct RustField {
94
94
paths : Vec < Vec < usize > > ,
95
95
}
96
96
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
+
97
105
enum RustAdt {
98
106
Struct ( IndexMap < IStr , RustField > ) ,
99
- Enum ( IndexMap < IStr , ( IRule , IndexMap < IStr , RustField > ) > ) ,
107
+ Enum ( IndexMap < IStr , ( IRule , RustVariant ) > ) ,
100
108
}
101
109
102
110
trait RuleWithFieldsMethods < Pat > {
@@ -198,11 +206,17 @@ impl<Pat: RustInputPat> RuleWithFieldsMethods<Pat> for RuleWithFields {
198
206
. enumerate ( )
199
207
. map ( |( i, & rule) | match cx[ children[ i] ] {
200
208
Fields :: Leaf ( Some ( field) ) => {
201
- let child = RuleWithFields {
209
+ let subfields = RuleWithFields {
202
210
rule,
203
211
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)
204
218
} ;
205
- Some ( ( field. name , ( rule, child . rust_fields ( cx ) ) ) )
219
+ Some ( ( field. name , ( rule, variant ) ) )
206
220
}
207
221
_ => None ,
208
222
} )
@@ -973,18 +987,20 @@ where
973
987
974
988
let rule_ty_def = match & rust_adt {
975
989
RustAdt :: Enum ( variants) => {
976
- let variants = variants. iter ( ) . map ( |( & v_name, ( v_rule , v_fields ) ) | {
990
+ let variants = variants. iter ( ) . map ( |( & v_name, ( _ , variant ) ) | {
977
991
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
+ }
988
1004
}
989
1005
} ) ;
990
1006
quote ! (
@@ -1063,20 +1079,21 @@ where
1063
1079
let variants_from_forest_ident = variants
1064
1080
. keys ( )
1065
1081
. 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 ) ) | {
1067
1083
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 {
1070
1086
node: _node,
1071
1087
forest,
1072
1088
_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
+ }
1080
1097
}
1081
1098
} ) ;
1082
1099
@@ -1239,42 +1256,46 @@ fn rule_debug_impl<Pat>(cx: &Context<Pat>, name: IStr, rust_adt: &RustAdt) -> Sr
1239
1256
let ident = Src :: ident ( name) ;
1240
1257
let body = match rust_adt {
1241
1258
RustAdt :: Enum ( variants) => {
1242
- let variants_pat = variants. iter ( ) . map ( |( & v_name, ( _, v_fields ) ) | {
1259
+ let variants_pat = variants. iter ( ) . map ( |( & v_name, ( _, variant ) ) | {
1243
1260
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
+ }
1254
1272
}
1255
1273
} ) ;
1256
- let variants_body = variants. iter ( ) . map ( |( & v_name, ( _, v_fields ) ) | {
1274
+ let variants_body = variants. iter ( ) . map ( |( & v_name, ( _, variant ) ) | {
1257
1275
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
+ } ) ;
1272
1292
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
+ }
1278
1299
}
1279
1300
} ) ;
1280
1301
0 commit comments