Skip to content

Commit 5c9c9a6

Browse files
committed
libsyntax: Parse common enum fields
1 parent 780b385 commit 5c9c9a6

File tree

5 files changed

+129
-86
lines changed

5 files changed

+129
-86
lines changed

src/libsyntax/ast.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -641,7 +641,7 @@ enum variant_kind {
641641
}
642642

643643
#[auto_serialize]
644-
enum enum_def = { variants: ~[variant] };
644+
enum enum_def = { variants: ~[variant], common: option<@struct_def> };
645645

646646
#[auto_serialize]
647647
type variant_ = {name: ident, attrs: ~[attribute], kind: variant_kind,

src/libsyntax/ext/pipes/pipec.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -231,7 +231,9 @@ impl state: to_type_decls {
231231
vec::push(items_msg, v);
232232
}
233233
234-
~[cx.item_enum_poly(name, ast::enum_def({ variants: items_msg }),
234+
~[cx.item_enum_poly(name,
235+
ast::enum_def({ variants: items_msg,
236+
common: none }),
235237
self.ty_params)]
236238
}
237239

src/libsyntax/fold.rs

Lines changed: 41 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -242,40 +242,13 @@ fn noop_fold_item_underscore(i: item_, fld: ast_fold) -> item_ {
242242
item_enum(ast::enum_def({
243243
variants: vec::map(enum_definition.variants,
244244
|x| fld.fold_variant(x)),
245+
common: option::map(enum_definition.common,
246+
|x| fold_struct_def(x, fld))
245247
}), fold_ty_params(typms, fld))
246248
}
247249
item_class(struct_def, typms) => {
248-
let resulting_optional_constructor;
249-
match struct_def.ctor {
250-
none => {
251-
resulting_optional_constructor = none;
252-
}
253-
some(constructor) => {
254-
resulting_optional_constructor = some({
255-
node: {
256-
body: fld.fold_block(constructor.node.body),
257-
dec: fold_fn_decl(constructor.node.dec, fld),
258-
id: fld.new_id(constructor.node.id)
259-
with constructor.node
260-
}
261-
with constructor
262-
});
263-
}
264-
}
265-
let dtor = do option::map(struct_def.dtor) |dtor| {
266-
let dtor_body = fld.fold_block(dtor.node.body);
267-
let dtor_id = fld.new_id(dtor.node.id);
268-
{node: {body: dtor_body,
269-
id: dtor_id with dtor.node}
270-
with dtor}};
271-
item_class(@{
272-
traits: vec::map(struct_def.traits,
273-
|p| fold_trait_ref(p, fld)),
274-
members: vec::map(struct_def.members,
275-
|x| fld.fold_class_item(x)),
276-
ctor: resulting_optional_constructor,
277-
dtor: dtor},
278-
/* FIXME (#2543) */ copy typms)
250+
let struct_def = fold_struct_def(struct_def, fld);
251+
item_class(struct_def, /* FIXME (#2543) */ copy typms)
279252
}
280253
item_impl(tps, ifce, ty, methods) => {
281254
item_impl(fold_ty_params(tps, fld),
@@ -295,6 +268,39 @@ fn noop_fold_item_underscore(i: item_, fld: ast_fold) -> item_ {
295268
};
296269
}
297270

271+
fn fold_struct_def(struct_def: @ast::struct_def, fld: ast_fold)
272+
-> @ast::struct_def {
273+
let resulting_optional_constructor;
274+
match struct_def.ctor {
275+
none => {
276+
resulting_optional_constructor = none;
277+
}
278+
some(constructor) => {
279+
resulting_optional_constructor = some({
280+
node: {
281+
body: fld.fold_block(constructor.node.body),
282+
dec: fold_fn_decl(constructor.node.dec, fld),
283+
id: fld.new_id(constructor.node.id)
284+
with constructor.node
285+
}
286+
with constructor
287+
});
288+
}
289+
}
290+
let dtor = do option::map(struct_def.dtor) |dtor| {
291+
let dtor_body = fld.fold_block(dtor.node.body);
292+
let dtor_id = fld.new_id(dtor.node.id);
293+
{node: {body: dtor_body,
294+
id: dtor_id with dtor.node}
295+
with dtor}};
296+
return @{
297+
traits: vec::map(struct_def.traits, |p| fold_trait_ref(p, fld)),
298+
members: vec::map(struct_def.members, |x| fld.fold_class_item(x)),
299+
ctor: resulting_optional_constructor,
300+
dtor: dtor
301+
};
302+
}
303+
298304
fn fold_trait_ref(&&p: @trait_ref, fld: ast_fold) -> @trait_ref {
299305
@{path: fld.fold_path(p.path), ref_id: fld.new_id(p.ref_id),
300306
impl_id: fld.new_id(p.impl_id)}
@@ -570,7 +576,10 @@ fn noop_fold_variant(v: variant_, fld: ast_fold) -> variant_ {
570576
enum_variant_kind(enum_definition) => {
571577
let variants = vec::map(enum_definition.variants,
572578
|x| fld.fold_variant(x));
573-
kind = enum_variant_kind(ast::enum_def({ variants: variants }));
579+
let common = option::map(enum_definition.common,
580+
|x| fold_struct_def(x, fld));
581+
kind = enum_variant_kind(ast::enum_def({ variants: variants,
582+
common: common }));
574583
}
575584
}
576585

src/libsyntax/parse/parser.rs

Lines changed: 70 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -46,9 +46,9 @@ import ast::{_mod, add, alt_check, alt_exhaustive, arg, arm, attribute,
4646
proto_block, proto_box, proto_uniq, provided, public, pure_fn,
4747
purity, re_anon, re_named, region, rem, required, ret_style,
4848
return_val, self_ty, shl, shr, stmt, stmt_decl, stmt_expr,
49-
stmt_semi, struct_variant_kind, subtract, sty_box, sty_by_ref,
50-
sty_region, sty_static, sty_uniq, sty_value, token_tree,
51-
trait_method, trait_ref, tt_delim, tt_seq, tt_tok,
49+
stmt_semi, struct_def, struct_variant_kind, subtract, sty_box,
50+
sty_by_ref, sty_region, sty_static, sty_uniq, sty_value,
51+
token_tree, trait_method, trait_ref, tt_delim, tt_seq, tt_tok,
5252
tt_nonterminal, ty, ty_, ty_bot, ty_box, ty_field, ty_fn,
5353
ty_infer, ty_mac, ty_method, ty_nil, ty_param, ty_param_bound,
5454
ty_path, ty_ptr, ty_rec, ty_rptr, ty_tup, ty_u32, ty_uniq,
@@ -2792,13 +2792,74 @@ class parser {
27922792
}
27932793
}
27942794

2795-
fn parse_enum_def(ty_params: ~[ast::ty_param]) -> enum_def {
2795+
fn parse_struct_def(path: @path) -> @struct_def {
2796+
let mut the_dtor: option<(blk, ~[attribute], codemap::span)> = none;
2797+
let mut ms: ~[@class_member] = ~[];
2798+
while self.token != token::RBRACE {
2799+
match self.parse_class_item(path) {
2800+
ctor_decl(*) => {
2801+
self.span_fatal(copy self.span,
2802+
~"deprecated explicit \
2803+
constructors are not allowed \
2804+
here");
2805+
}
2806+
dtor_decl(blk, attrs, s) => {
2807+
match the_dtor {
2808+
some((_, _, s_first)) => {
2809+
self.span_note(s, ~"duplicate destructor \
2810+
declaration");
2811+
self.span_fatal(copy s_first,
2812+
~"first destructor \
2813+
declared here");
2814+
}
2815+
none => {
2816+
the_dtor = some((blk, attrs, s));
2817+
}
2818+
}
2819+
}
2820+
members(mms) =>
2821+
ms = vec::append(ms, mms)
2822+
}
2823+
}
2824+
self.bump();
2825+
let mut actual_dtor = do option::map(the_dtor) |dtor| {
2826+
let (d_body, d_attrs, d_s) = dtor;
2827+
{node: {id: self.get_id(),
2828+
attrs: d_attrs,
2829+
self_id: self.get_id(),
2830+
body: d_body},
2831+
span: d_s}
2832+
};
2833+
2834+
return @{
2835+
traits: ~[],
2836+
members: ms,
2837+
ctor: none,
2838+
dtor: actual_dtor
2839+
};
2840+
}
2841+
2842+
fn parse_enum_def(ident: ast::ident, ty_params: ~[ast::ty_param])
2843+
-> enum_def {
27962844
let mut variants: ~[variant] = ~[];
27972845
let mut all_nullary = true, have_disr = false;
2846+
let mut common_fields = none;
27982847

27992848
while self.token != token::RBRACE {
28002849
let variant_attrs = self.parse_outer_attributes();
28012850
let vlo = self.span.lo;
2851+
2852+
// Is this a common field declaration?
2853+
if self.eat_keyword(~"struct") {
2854+
if common_fields.is_some() {
2855+
self.fatal(~"duplicate declaration of shared fields");
2856+
}
2857+
self.expect(token::LBRACE);
2858+
let path = self.ident_to_path_tys(ident, ty_params);
2859+
common_fields = some(self.parse_struct_def(path));
2860+
again;
2861+
}
2862+
28022863
let vis = self.parse_visibility();
28032864
let ident = self.parse_value_ident();
28042865
let mut args = ~[], disr_expr = none;
@@ -2807,51 +2868,7 @@ class parser {
28072868
// Parse a struct variant.
28082869
all_nullary = false;
28092870
let path = self.ident_to_path_tys(ident, ty_params);
2810-
let mut the_dtor: option<(blk, ~[attribute], codemap::span)> =
2811-
none;
2812-
let mut ms: ~[@class_member] = ~[];
2813-
while self.token != token::RBRACE {
2814-
match self.parse_class_item(path) {
2815-
ctor_decl(*) => {
2816-
self.span_fatal(copy self.span,
2817-
~"deprecated explicit \
2818-
constructors are not allowed \
2819-
here");
2820-
}
2821-
dtor_decl(blk, attrs, s) => {
2822-
match the_dtor {
2823-
some((_, _, s_first)) => {
2824-
self.span_note(s, ~"duplicate destructor \
2825-
declaration");
2826-
self.span_fatal(copy s_first,
2827-
~"first destructor \
2828-
declared here");
2829-
}
2830-
none => {
2831-
the_dtor = some((blk, attrs, s));
2832-
}
2833-
}
2834-
}
2835-
members(mms) =>
2836-
ms = vec::append(ms, mms)
2837-
}
2838-
}
2839-
self.bump();
2840-
let mut actual_dtor = do option::map(the_dtor) |dtor| {
2841-
let (d_body, d_attrs, d_s) = dtor;
2842-
{node: {id: self.get_id(),
2843-
attrs: d_attrs,
2844-
self_id: self.get_id(),
2845-
body: d_body},
2846-
span: d_s}
2847-
};
2848-
2849-
kind = struct_variant_kind(@{
2850-
traits: ~[],
2851-
members: ms,
2852-
ctor: none,
2853-
dtor: actual_dtor
2854-
});
2871+
kind = struct_variant_kind(self.parse_struct_def(path));
28552872
} else if self.token == token::LPAREN {
28562873
all_nullary = false;
28572874
let arg_tys = self.parse_unspanned_seq(
@@ -2883,7 +2900,7 @@ class parser {
28832900
enum");
28842901
}
28852902

2886-
return enum_def({ variants: variants });
2903+
return enum_def({ variants: variants, common: common_fields });
28872904
}
28882905

28892906
fn parse_item_enum() -> item_info {
@@ -2905,12 +2922,13 @@ class parser {
29052922
id: self.get_id(),
29062923
disr_expr: none,
29072924
vis: public});
2908-
return (id, item_enum(enum_def({ variants: ~[variant] }),
2925+
return (id, item_enum(enum_def({ variants: ~[variant],
2926+
common: none }),
29092927
ty_params), none);
29102928
}
29112929
self.expect(token::LBRACE);
29122930

2913-
let enum_definition = self.parse_enum_def(ty_params);
2931+
let enum_definition = self.parse_enum_def(id, ty_params);
29142932
(id, item_enum(enum_definition, ty_params), none)
29152933
}
29162934

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
enum Foo {
2+
struct {
3+
x: int;
4+
y: int;
5+
}
6+
7+
Bar(int),
8+
Baz(int)
9+
}
10+
11+
fn main() {
12+
let x = Bar(3);
13+
}
14+

0 commit comments

Comments
 (0)