Allow 'newtype' syntax for tags

Doing this:

    tag foo = mytype;

is now equivalent to doing this:

    tag foo { foo(mytype); }
This commit is contained in:
Marijn Haverbeke 2011-07-01 13:03:05 +02:00
parent fb72be0a89
commit 57e6340253
2 changed files with 48 additions and 17 deletions

View File

@ -945,7 +945,7 @@ fn parse_bottom_expr(&parser p) -> @ast::expr {
hi = es.span.hi;
ex = ast::expr_call(f, es.node);
} else if (is_ident(p.peek()) && !is_word(p, "true") &&
!is_word(p, "false")) {
!is_word(p, "false")) {
check_bad_word(p);
auto pth = parse_path_and_ty_param_substs(p);
hi = pth.span.hi;
@ -1979,6 +1979,21 @@ fn parse_item_tag(&parser p, vec[ast::attribute] attrs) -> @ast::item {
auto id = parse_ident(p);
auto ty_params = parse_ty_params(p);
let vec[ast::variant] variants = [];
// Newtype syntax
if (p.peek() == token::EQ) {
if (p.get_bad_expr_words().contains_key(id)) {
p.fatal("found " + id + " in tag constructor position");
}
p.bump();
auto ty = parse_ty(p);
expect(p, token::SEMI);
auto variant = spanned(ty.span.lo, ty.span.hi,
rec(name=id,
args=[rec(ty=ty, id=p.get_id())],
id=p.get_id()));
ret mk_item(p, lo, ty.span.hi, id,
ast::item_tag([variant], ty_params), attrs);
}
expect(p, token::LBRACE);
while (p.peek() != token::RBRACE) {
auto tok = p.peek();

View File

@ -383,27 +383,43 @@ fn print_item(&ps s, &@ast::item item) {
break_offset(s.s, 0u, 0);
}
case (ast::item_tag(?variants, ?params)) {
head(s, "tag");
auto newtype = vec::len(variants) == 1u &&
str::eq(item.ident, variants.(0).node.name) &&
vec::len(variants.(0).node.args) == 1u;
if (newtype) {
ibox(s, indent_unit);
word_space(s, "tag");
} else {
head(s, "tag");
}
word(s.s, item.ident);
print_type_params(s, params);
space(s.s);
bopen(s);
for (ast::variant v in variants) {
space(s.s);
maybe_print_comment(s, v.span.lo);
word(s.s, v.node.name);
if (vec::len(v.node.args) > 0u) {
popen(s);
fn print_variant_arg(&ps s, &ast::variant_arg arg) {
print_type(s, *arg.ty);
}
commasep(s, consistent, v.node.args, print_variant_arg);
pclose(s);
}
if (newtype) {
word_space(s, "=");
print_type(s, *variants.(0).node.args.(0).ty);
word(s.s, ";");
maybe_print_trailing_comment(s, v.span, none[uint]);
end(s);
} else {
bopen(s);
for (ast::variant v in variants) {
space(s.s);
maybe_print_comment(s, v.span.lo);
word(s.s, v.node.name);
if (vec::len(v.node.args) > 0u) {
popen(s);
fn print_variant_arg(&ps s, &ast::variant_arg arg) {
print_type(s, *arg.ty);
}
commasep(s, consistent, v.node.args,
print_variant_arg);
pclose(s);
}
word(s.s, ";");
maybe_print_trailing_comment(s, v.span, none[uint]);
}
bclose(s, item.span);
}
bclose(s, item.span);
}
case (ast::item_obj(?_obj, ?params, _)) {
head(s, "obj");