Skip to content

Commit

Permalink
libsyntax: Parse common enum fields
Browse files Browse the repository at this point in the history
  • Loading branch information
pcwalton committed Aug 9, 2012
1 parent 780b385 commit 5c9c9a6
Show file tree
Hide file tree
Showing 5 changed files with 129 additions and 86 deletions.
2 changes: 1 addition & 1 deletion src/libsyntax/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
4 changes: 3 additions & 1 deletion src/libsyntax/ext/pipes/pipec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)]
}

Expand Down
73 changes: 41 additions & 32 deletions src/libsyntax/fold.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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),
Expand All @@ -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)}
Expand Down Expand Up @@ -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 }));
}
}

Expand Down
122 changes: 70 additions & 52 deletions src/libsyntax/parse/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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;
Expand All @@ -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(
Expand Down Expand Up @@ -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 {
Expand All @@ -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)
}

Expand Down
14 changes: 14 additions & 0 deletions src/test/run-pass/common-fields-trivial.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
enum Foo {
struct {
x: int;
y: int;
}

Bar(int),
Baz(int)
}

fn main() {
let x = Bar(3);
}

0 comments on commit 5c9c9a6

Please sign in to comment.