libsyntax: Parse common enum fields

This commit is contained in:
Patrick Walton 2012-08-08 19:51:19 -07:00
parent 780b3853d1
commit 5c9c9a6a9f
5 changed files with 129 additions and 86 deletions

View file

@ -641,7 +641,7 @@ enum variant_kind {
} }
#[auto_serialize] #[auto_serialize]
enum enum_def = { variants: ~[variant] }; enum enum_def = { variants: ~[variant], common: option<@struct_def> };
#[auto_serialize] #[auto_serialize]
type variant_ = {name: ident, attrs: ~[attribute], kind: variant_kind, type variant_ = {name: ident, attrs: ~[attribute], kind: variant_kind,

View file

@ -231,7 +231,9 @@ impl state: to_type_decls {
vec::push(items_msg, v); vec::push(items_msg, v);
} }
~[cx.item_enum_poly(name, ast::enum_def({ variants: items_msg }), ~[cx.item_enum_poly(name,
ast::enum_def({ variants: items_msg,
common: none }),
self.ty_params)] self.ty_params)]
} }

View file

@ -242,9 +242,34 @@ fn noop_fold_item_underscore(i: item_, fld: ast_fold) -> item_ {
item_enum(ast::enum_def({ item_enum(ast::enum_def({
variants: vec::map(enum_definition.variants, variants: vec::map(enum_definition.variants,
|x| fld.fold_variant(x)), |x| fld.fold_variant(x)),
common: option::map(enum_definition.common,
|x| fold_struct_def(x, fld))
}), fold_ty_params(typms, fld)) }), fold_ty_params(typms, fld))
} }
item_class(struct_def, typms) => { item_class(struct_def, typms) => {
let struct_def = fold_struct_def(struct_def, fld);
item_class(struct_def, /* FIXME (#2543) */ copy typms)
}
item_impl(tps, ifce, ty, methods) => {
item_impl(fold_ty_params(tps, fld),
ifce.map(|p| fold_trait_ref(p, fld)),
fld.fold_ty(ty),
vec::map(methods, |x| fld.fold_method(x)))
}
item_trait(tps, traits, methods) => {
item_trait(fold_ty_params(tps, fld),
vec::map(traits, |p| fold_trait_ref(p, fld)),
/* FIXME (#2543) */ copy methods)
}
item_mac(m) => {
// FIXME #2888: we might actually want to do something here.
item_mac(m)
}
};
}
fn fold_struct_def(struct_def: @ast::struct_def, fld: ast_fold)
-> @ast::struct_def {
let resulting_optional_constructor; let resulting_optional_constructor;
match struct_def.ctor { match struct_def.ctor {
none => { none => {
@ -268,30 +293,11 @@ fn noop_fold_item_underscore(i: item_, fld: ast_fold) -> item_ {
{node: {body: dtor_body, {node: {body: dtor_body,
id: dtor_id with dtor.node} id: dtor_id with dtor.node}
with dtor}}; with dtor}};
item_class(@{ return @{
traits: vec::map(struct_def.traits, traits: vec::map(struct_def.traits, |p| fold_trait_ref(p, fld)),
|p| fold_trait_ref(p, fld)), members: vec::map(struct_def.members, |x| fld.fold_class_item(x)),
members: vec::map(struct_def.members,
|x| fld.fold_class_item(x)),
ctor: resulting_optional_constructor, ctor: resulting_optional_constructor,
dtor: dtor}, dtor: dtor
/* FIXME (#2543) */ copy typms)
}
item_impl(tps, ifce, ty, methods) => {
item_impl(fold_ty_params(tps, fld),
ifce.map(|p| fold_trait_ref(p, fld)),
fld.fold_ty(ty),
vec::map(methods, |x| fld.fold_method(x)))
}
item_trait(tps, traits, methods) => {
item_trait(fold_ty_params(tps, fld),
vec::map(traits, |p| fold_trait_ref(p, fld)),
/* FIXME (#2543) */ copy methods)
}
item_mac(m) => {
// FIXME #2888: we might actually want to do something here.
item_mac(m)
}
}; };
} }
@ -570,7 +576,10 @@ fn noop_fold_variant(v: variant_, fld: ast_fold) -> variant_ {
enum_variant_kind(enum_definition) => { enum_variant_kind(enum_definition) => {
let variants = vec::map(enum_definition.variants, let variants = vec::map(enum_definition.variants,
|x| fld.fold_variant(x)); |x| fld.fold_variant(x));
kind = enum_variant_kind(ast::enum_def({ variants: variants })); let common = option::map(enum_definition.common,
|x| fold_struct_def(x, fld));
kind = enum_variant_kind(ast::enum_def({ variants: variants,
common: common }));
} }
} }

View file

@ -46,9 +46,9 @@ import ast::{_mod, add, alt_check, alt_exhaustive, arg, arm, attribute,
proto_block, proto_box, proto_uniq, provided, public, pure_fn, proto_block, proto_box, proto_uniq, provided, public, pure_fn,
purity, re_anon, re_named, region, rem, required, ret_style, purity, re_anon, re_named, region, rem, required, ret_style,
return_val, self_ty, shl, shr, stmt, stmt_decl, stmt_expr, return_val, self_ty, shl, shr, stmt, stmt_decl, stmt_expr,
stmt_semi, struct_variant_kind, subtract, sty_box, sty_by_ref, stmt_semi, struct_def, struct_variant_kind, subtract, sty_box,
sty_region, sty_static, sty_uniq, sty_value, token_tree, sty_by_ref, sty_region, sty_static, sty_uniq, sty_value,
trait_method, trait_ref, tt_delim, tt_seq, tt_tok, token_tree, trait_method, trait_ref, tt_delim, tt_seq, tt_tok,
tt_nonterminal, ty, ty_, ty_bot, ty_box, ty_field, ty_fn, tt_nonterminal, ty, ty_, ty_bot, ty_box, ty_field, ty_fn,
ty_infer, ty_mac, ty_method, ty_nil, ty_param, ty_param_bound, ty_infer, ty_mac, ty_method, ty_nil, ty_param, ty_param_bound,
ty_path, ty_ptr, ty_rec, ty_rptr, ty_tup, ty_u32, ty_uniq, ty_path, ty_ptr, ty_rec, ty_rptr, ty_tup, ty_u32, ty_uniq,
@ -2792,23 +2792,8 @@ class parser {
} }
} }
fn parse_enum_def(ty_params: ~[ast::ty_param]) -> enum_def { fn parse_struct_def(path: @path) -> @struct_def {
let mut variants: ~[variant] = ~[]; let mut the_dtor: option<(blk, ~[attribute], codemap::span)> = none;
let mut all_nullary = true, have_disr = false;
while self.token != token::RBRACE {
let variant_attrs = self.parse_outer_attributes();
let vlo = self.span.lo;
let vis = self.parse_visibility();
let ident = self.parse_value_ident();
let mut args = ~[], disr_expr = none;
let kind;
if self.eat(token::LBRACE) {
// Parse a struct variant.
all_nullary = false;
let path = self.ident_to_path_tys(ident, ty_params);
let mut the_dtor: option<(blk, ~[attribute], codemap::span)> =
none;
let mut ms: ~[@class_member] = ~[]; let mut ms: ~[@class_member] = ~[];
while self.token != token::RBRACE { while self.token != token::RBRACE {
match self.parse_class_item(path) { match self.parse_class_item(path) {
@ -2846,12 +2831,44 @@ class parser {
span: d_s} span: d_s}
}; };
kind = struct_variant_kind(@{ return @{
traits: ~[], traits: ~[],
members: ms, members: ms,
ctor: none, ctor: none,
dtor: actual_dtor dtor: actual_dtor
}); };
}
fn parse_enum_def(ident: ast::ident, ty_params: ~[ast::ty_param])
-> enum_def {
let mut variants: ~[variant] = ~[];
let mut all_nullary = true, have_disr = false;
let mut common_fields = none;
while self.token != token::RBRACE {
let variant_attrs = self.parse_outer_attributes();
let vlo = self.span.lo;
// Is this a common field declaration?
if self.eat_keyword(~"struct") {
if common_fields.is_some() {
self.fatal(~"duplicate declaration of shared fields");
}
self.expect(token::LBRACE);
let path = self.ident_to_path_tys(ident, ty_params);
common_fields = some(self.parse_struct_def(path));
again;
}
let vis = self.parse_visibility();
let ident = self.parse_value_ident();
let mut args = ~[], disr_expr = none;
let kind;
if self.eat(token::LBRACE) {
// Parse a struct variant.
all_nullary = false;
let path = self.ident_to_path_tys(ident, ty_params);
kind = struct_variant_kind(self.parse_struct_def(path));
} else if self.token == token::LPAREN { } else if self.token == token::LPAREN {
all_nullary = false; all_nullary = false;
let arg_tys = self.parse_unspanned_seq( let arg_tys = self.parse_unspanned_seq(
@ -2883,7 +2900,7 @@ class parser {
enum"); enum");
} }
return enum_def({ variants: variants }); return enum_def({ variants: variants, common: common_fields });
} }
fn parse_item_enum() -> item_info { fn parse_item_enum() -> item_info {
@ -2905,12 +2922,13 @@ class parser {
id: self.get_id(), id: self.get_id(),
disr_expr: none, disr_expr: none,
vis: public}); vis: public});
return (id, item_enum(enum_def({ variants: ~[variant] }), return (id, item_enum(enum_def({ variants: ~[variant],
common: none }),
ty_params), none); ty_params), none);
} }
self.expect(token::LBRACE); self.expect(token::LBRACE);
let enum_definition = self.parse_enum_def(ty_params); let enum_definition = self.parse_enum_def(id, ty_params);
(id, item_enum(enum_definition, ty_params), none) (id, item_enum(enum_definition, ty_params), none)
} }

View file

@ -0,0 +1,14 @@
enum Foo {
struct {
x: int;
y: int;
}
Bar(int),
Baz(int)
}
fn main() {
let x = Bar(3);
}