libsyntax: Parse common enum fields
This commit is contained in:
parent
780b3853d1
commit
5c9c9a6a9f
@ -641,7 +641,7 @@ enum variant_kind {
|
||||
}
|
||||
|
||||
#[auto_serialize]
|
||||
enum enum_def = { variants: ~[variant] };
|
||||
enum enum_def = { variants: ~[variant], common: option<@struct_def> };
|
||||
|
||||
#[auto_serialize]
|
||||
type variant_ = {name: ident, attrs: ~[attribute], kind: variant_kind,
|
||||
|
@ -231,7 +231,9 @@ impl state: to_type_decls {
|
||||
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)]
|
||||
}
|
||||
|
||||
|
@ -242,40 +242,13 @@ fn noop_fold_item_underscore(i: item_, fld: ast_fold) -> item_ {
|
||||
item_enum(ast::enum_def({
|
||||
variants: vec::map(enum_definition.variants,
|
||||
|x| fld.fold_variant(x)),
|
||||
common: option::map(enum_definition.common,
|
||||
|x| fold_struct_def(x, fld))
|
||||
}), fold_ty_params(typms, fld))
|
||||
}
|
||||
item_class(struct_def, typms) => {
|
||||
let resulting_optional_constructor;
|
||||
match struct_def.ctor {
|
||||
none => {
|
||||
resulting_optional_constructor = none;
|
||||
}
|
||||
some(constructor) => {
|
||||
resulting_optional_constructor = some({
|
||||
node: {
|
||||
body: fld.fold_block(constructor.node.body),
|
||||
dec: fold_fn_decl(constructor.node.dec, fld),
|
||||
id: fld.new_id(constructor.node.id)
|
||||
with constructor.node
|
||||
}
|
||||
with constructor
|
||||
});
|
||||
}
|
||||
}
|
||||
let dtor = do option::map(struct_def.dtor) |dtor| {
|
||||
let dtor_body = fld.fold_block(dtor.node.body);
|
||||
let dtor_id = fld.new_id(dtor.node.id);
|
||||
{node: {body: dtor_body,
|
||||
id: dtor_id with dtor.node}
|
||||
with dtor}};
|
||||
item_class(@{
|
||||
traits: vec::map(struct_def.traits,
|
||||
|p| fold_trait_ref(p, fld)),
|
||||
members: vec::map(struct_def.members,
|
||||
|x| fld.fold_class_item(x)),
|
||||
ctor: resulting_optional_constructor,
|
||||
dtor: dtor},
|
||||
/* FIXME (#2543) */ copy 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),
|
||||
@ -295,6 +268,39 @@ fn noop_fold_item_underscore(i: item_, fld: ast_fold) -> item_ {
|
||||
};
|
||||
}
|
||||
|
||||
fn fold_struct_def(struct_def: @ast::struct_def, fld: ast_fold)
|
||||
-> @ast::struct_def {
|
||||
let resulting_optional_constructor;
|
||||
match struct_def.ctor {
|
||||
none => {
|
||||
resulting_optional_constructor = none;
|
||||
}
|
||||
some(constructor) => {
|
||||
resulting_optional_constructor = some({
|
||||
node: {
|
||||
body: fld.fold_block(constructor.node.body),
|
||||
dec: fold_fn_decl(constructor.node.dec, fld),
|
||||
id: fld.new_id(constructor.node.id)
|
||||
with constructor.node
|
||||
}
|
||||
with constructor
|
||||
});
|
||||
}
|
||||
}
|
||||
let dtor = do option::map(struct_def.dtor) |dtor| {
|
||||
let dtor_body = fld.fold_block(dtor.node.body);
|
||||
let dtor_id = fld.new_id(dtor.node.id);
|
||||
{node: {body: dtor_body,
|
||||
id: dtor_id with dtor.node}
|
||||
with dtor}};
|
||||
return @{
|
||||
traits: vec::map(struct_def.traits, |p| fold_trait_ref(p, fld)),
|
||||
members: vec::map(struct_def.members, |x| fld.fold_class_item(x)),
|
||||
ctor: resulting_optional_constructor,
|
||||
dtor: dtor
|
||||
};
|
||||
}
|
||||
|
||||
fn fold_trait_ref(&&p: @trait_ref, fld: ast_fold) -> @trait_ref {
|
||||
@{path: fld.fold_path(p.path), ref_id: fld.new_id(p.ref_id),
|
||||
impl_id: fld.new_id(p.impl_id)}
|
||||
@ -570,7 +576,10 @@ fn noop_fold_variant(v: variant_, fld: ast_fold) -> variant_ {
|
||||
enum_variant_kind(enum_definition) => {
|
||||
let variants = vec::map(enum_definition.variants,
|
||||
|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 }));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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,
|
||||
purity, re_anon, re_named, region, rem, required, ret_style,
|
||||
return_val, self_ty, shl, shr, stmt, stmt_decl, stmt_expr,
|
||||
stmt_semi, struct_variant_kind, subtract, sty_box, sty_by_ref,
|
||||
sty_region, sty_static, sty_uniq, sty_value, token_tree,
|
||||
trait_method, trait_ref, tt_delim, tt_seq, tt_tok,
|
||||
stmt_semi, struct_def, struct_variant_kind, subtract, sty_box,
|
||||
sty_by_ref, sty_region, sty_static, sty_uniq, sty_value,
|
||||
token_tree, trait_method, trait_ref, tt_delim, tt_seq, tt_tok,
|
||||
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_path, ty_ptr, ty_rec, ty_rptr, ty_tup, ty_u32, ty_uniq,
|
||||
@ -2792,13 +2792,74 @@ class parser {
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_enum_def(ty_params: ~[ast::ty_param]) -> enum_def {
|
||||
fn parse_struct_def(path: @path) -> @struct_def {
|
||||
let mut the_dtor: option<(blk, ~[attribute], codemap::span)> = none;
|
||||
let mut ms: ~[@class_member] = ~[];
|
||||
while self.token != token::RBRACE {
|
||||
match self.parse_class_item(path) {
|
||||
ctor_decl(*) => {
|
||||
self.span_fatal(copy self.span,
|
||||
~"deprecated explicit \
|
||||
constructors are not allowed \
|
||||
here");
|
||||
}
|
||||
dtor_decl(blk, attrs, s) => {
|
||||
match the_dtor {
|
||||
some((_, _, s_first)) => {
|
||||
self.span_note(s, ~"duplicate destructor \
|
||||
declaration");
|
||||
self.span_fatal(copy s_first,
|
||||
~"first destructor \
|
||||
declared here");
|
||||
}
|
||||
none => {
|
||||
the_dtor = some((blk, attrs, s));
|
||||
}
|
||||
}
|
||||
}
|
||||
members(mms) =>
|
||||
ms = vec::append(ms, mms)
|
||||
}
|
||||
}
|
||||
self.bump();
|
||||
let mut actual_dtor = do option::map(the_dtor) |dtor| {
|
||||
let (d_body, d_attrs, d_s) = dtor;
|
||||
{node: {id: self.get_id(),
|
||||
attrs: d_attrs,
|
||||
self_id: self.get_id(),
|
||||
body: d_body},
|
||||
span: d_s}
|
||||
};
|
||||
|
||||
return @{
|
||||
traits: ~[],
|
||||
members: ms,
|
||||
ctor: none,
|
||||
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;
|
||||
@ -2807,51 +2868,7 @@ class parser {
|
||||
// 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] = ~[];
|
||||
while self.token != token::RBRACE {
|
||||
match self.parse_class_item(path) {
|
||||
ctor_decl(*) => {
|
||||
self.span_fatal(copy self.span,
|
||||
~"deprecated explicit \
|
||||
constructors are not allowed \
|
||||
here");
|
||||
}
|
||||
dtor_decl(blk, attrs, s) => {
|
||||
match the_dtor {
|
||||
some((_, _, s_first)) => {
|
||||
self.span_note(s, ~"duplicate destructor \
|
||||
declaration");
|
||||
self.span_fatal(copy s_first,
|
||||
~"first destructor \
|
||||
declared here");
|
||||
}
|
||||
none => {
|
||||
the_dtor = some((blk, attrs, s));
|
||||
}
|
||||
}
|
||||
}
|
||||
members(mms) =>
|
||||
ms = vec::append(ms, mms)
|
||||
}
|
||||
}
|
||||
self.bump();
|
||||
let mut actual_dtor = do option::map(the_dtor) |dtor| {
|
||||
let (d_body, d_attrs, d_s) = dtor;
|
||||
{node: {id: self.get_id(),
|
||||
attrs: d_attrs,
|
||||
self_id: self.get_id(),
|
||||
body: d_body},
|
||||
span: d_s}
|
||||
};
|
||||
|
||||
kind = struct_variant_kind(@{
|
||||
traits: ~[],
|
||||
members: ms,
|
||||
ctor: none,
|
||||
dtor: actual_dtor
|
||||
});
|
||||
kind = struct_variant_kind(self.parse_struct_def(path));
|
||||
} else if self.token == token::LPAREN {
|
||||
all_nullary = false;
|
||||
let arg_tys = self.parse_unspanned_seq(
|
||||
@ -2883,7 +2900,7 @@ class parser {
|
||||
enum");
|
||||
}
|
||||
|
||||
return enum_def({ variants: variants });
|
||||
return enum_def({ variants: variants, common: common_fields });
|
||||
}
|
||||
|
||||
fn parse_item_enum() -> item_info {
|
||||
@ -2905,12 +2922,13 @@ class parser {
|
||||
id: self.get_id(),
|
||||
disr_expr: none,
|
||||
vis: public});
|
||||
return (id, item_enum(enum_def({ variants: ~[variant] }),
|
||||
return (id, item_enum(enum_def({ variants: ~[variant],
|
||||
common: none }),
|
||||
ty_params), none);
|
||||
}
|
||||
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)
|
||||
}
|
||||
|
||||
|
14
src/test/run-pass/common-fields-trivial.rs
Normal file
14
src/test/run-pass/common-fields-trivial.rs
Normal file
@ -0,0 +1,14 @@
|
||||
enum Foo {
|
||||
struct {
|
||||
x: int;
|
||||
y: int;
|
||||
}
|
||||
|
||||
Bar(int),
|
||||
Baz(int)
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let x = Bar(3);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user