Export all enum variants by default; new syntax for selectively exporting variants

See issue 1426 for details. Now, the semantics of "export t;" where t is a tag are
to export all of t's variants as well. "export t{};" exports t but not its
variants, while "export t{a, b, c};" exports only variants a, b, c of t.

To do:
- documentation
- there's currently no checking that a, b, c are actually variants of t in the
 above example
- there's also no checking that t is an enum type, in the second two examples above
- change the modules listed in issue 1426 that should have the old export
semantics to use the t{} syntax

I deleted the test export-no-tag-variants since we're doing the opposite now,
and other tests cover the same behavior.
This commit is contained in:
Tim Chevalier 2012-01-22 21:09:43 -08:00
parent e515999324
commit 9dc59e1506
10 changed files with 89 additions and 63 deletions

View File

@ -1403,6 +1403,8 @@ fn index_mod(md: ast::_mod) -> mod_index {
}
//globbed imports have to be resolved lazily.
ast::view_item_import_glob(_, _) | ast::view_item_export(_, _) {}
// exports: ignore
_ {}
}
}
for it: @ast::item in md.items {

View File

@ -442,7 +442,7 @@ enum view_item_ {
// export foo::{}
view_item_export_tag_none(ident, node_id),
// export foo::{bar, baz, blat}
view_item_export_tag_some(ident, [ident], node_id)
view_item_export_tag_some(ident, [import_ident], node_id)
}
// Meta-data associated with an item

View File

@ -113,12 +113,16 @@ fn float_ty_to_str(t: float_ty) -> str {
fn is_exported(i: ident, m: _mod) -> bool {
let nonlocal = true;
let parent_tag : option<ident> = none;
for it: @item in m.items {
if it.ident == i { nonlocal = false; }
alt it.node {
item_tag(variants, _) {
for v: variant in variants {
if v.node.name == i { nonlocal = false; }
if v.node.name == i {
nonlocal = false;
parent_tag = some(it.ident);
}
}
}
_ { }
@ -129,9 +133,28 @@ fn is_exported(i: ident, m: _mod) -> bool {
for vi: @view_item in m.view_items {
alt vi.node {
view_item_export(ids, _) {
for id in ids { if str::eq(i, id) { ret true; } }
// If any of ids is a tag, we want to consider
// all the variants to be exported
for id in ids {
if str::eq(i, id) { ret true; }
alt parent_tag {
some(parent_tag_id) {
if str::eq(id, parent_tag_id) { ret true; }
}
_ { }
}
}
count += 1u;
}
view_item_export_tag_none(id, _) {
if str::eq(i, id) { ret true; }
count += 1u;
}
view_item_export_tag_some(id, ids, _) {
if str::eq(i, id) { ret true; }
for id in ids { if str::eq(i, id.node.name) { ret true; } }
count += 1u;
}
_ {/* fall through */ }
}
}

View File

@ -194,10 +194,18 @@ fn spanned<T: copy>(lo: uint, hi: uint, node: T) -> spanned<T> {
fn parse_ident(p: parser) -> ast::ident {
alt p.token {
token::IDENT(i, _) { p.bump(); ret p.get_str(i); }
_ { p.fatal("expecting ident"); }
_ { p.fatal("expecting ident, found "
+ token::to_str(p.reader, p.token)); }
}
}
fn parse_import_ident(p: parser) -> ast::import_ident {
let lo = p.span.lo;
let ident = parse_ident(p);
let hi = p.span.hi;
ret spanned(lo, hi, {name: ident, id: p.get_id()});
}
fn parse_value_ident(p: parser) -> ast::ident {
check_bad_word(p);
ret parse_ident(p);
@ -2316,12 +2324,6 @@ fn parse_rest_import_name(p: parser, first: ast::ident,
token::LBRACE {
fn parse_import_ident(p: parser) -> ast::import_ident {
let lo = p.span.lo;
let ident = parse_ident(p);
let hi = p.span.hi;
ret spanned(lo, hi, {name: ident, id: p.get_id()});
}
let from_idents_ =
parse_seq(token::LBRACE, token::RBRACE, seq_sep(token::COMMA),
parse_import_ident, p).node;
@ -2392,9 +2394,9 @@ fn parse_import(p: parser) -> ast::view_item_ {
}
fn parse_tag_export(p:parser, tyname:ast::ident) -> ast::view_item_ {
let tagnames:[ast::ident] =
let tagnames:[ast::import_ident] =
parse_seq(token::LBRACE, token::RBRACE,
seq_sep(token::COMMA), {|p| parse_ident(p) }, p).node;
seq_sep(token::COMMA), {|p| parse_import_ident(p) }, p).node;
let id = p.get_id();
if vec::is_empty(tagnames) {
ret ast::view_item_export_tag_none(tyname, id);
@ -2407,9 +2409,8 @@ fn parse_tag_export(p:parser, tyname:ast::ident) -> ast::view_item_ {
fn parse_export(p: parser) -> ast::view_item_ {
let first = parse_ident(p);
alt p.token {
token::COLON {
token::MOD_SEP {
p.bump();
expect(p, token::COLON);
ret parse_tag_export(p, first);
}
t {

View File

@ -1303,6 +1303,19 @@ fn print_view_item(s: ps, item: @ast::view_item) {
commasep(s, inconsistent, ids,
fn@(s: ps, &&w: ast::ident) { word(s.s, w) });
}
ast::view_item_export_tag_none(id, _) {
head(s, "export");
word(s.s, id);
word(s.s, "::{}");
}
ast::view_item_export_tag_some(id, ids, _) {
head(s, "export");
word(s.s, id);
word(s.s, "::{");
commasep(s, inconsistent, ids, fn@(s:ps, &&w: ast::import_ident) {
word(s.s, w.node.name) });
word(s.s, "}");
}
}
word(s.s, ";");
end(s); // end inner head-block

View File

@ -1,12 +0,0 @@
// error-pattern: unresolved name
// Tag variants are not exported with their tags. This allows for a
// simple sort of ADT.
mod foo {
export t;
enum t { t1, }
}
fn main() { let x = foo::t1; }

View File

@ -1,18 +1,18 @@
// xfail-test
// error-pattern:unresolved name: lovejoy
import alder::*;
mod alder {
export burnside;
export everett::{flanders};
export irving::{johnson, kearney};
export marshall::{};
tag burnside { couch, davis }
tag everett { flanders, glisan, hoyt }
tag irving { johnson, kearney, lovejoy }
tag marshall { northrup, overton }
enum burnside { couch, davis }
enum everett { flanders, glisan, hoyt }
enum irving { johnson, kearney, lovejoy }
enum marshall { northrup, overton }
}
import alder::*;
fn main() {
let raleigh: irving = lovejoy;
}
}

View File

@ -1,19 +1,18 @@
// xfail-test
// error-pattern:unresolved name: northrup
import alder::*;
mod alder {
export burnside;
export everett::{flanders};
export irving::{johnson, kearney};
export marshall::{};
tag burnside { couch, davis }
tag everett { flanders, glisan, hoyt }
tag irving { johnson, kearney, lovejoy }
tag marshall { northrup, overton }
enum burnside { couch, davis }
enum everett { flanders, glisan, hoyt }
enum irving { johnson, kearney, lovejoy }
enum marshall { northrup, overton }
}
import alder::*;
fn main() {
let savier: marshall = northrup;
}
}

View File

@ -1,18 +1,18 @@
// xfail-test
// error-pattern:unresolved name: glisan
import alder::*;
mod alder {
export burnside;
export everett::{flanders};
export irving::{johnson, kearney};
export marshall::{};
tag burnside { couch, davis }
tag everett { flanders, glisan, hoyt }
tag irving { johnson, kearney, lovejoy }
tag marshall { northrup, overton }
enum burnside { couch, davis }
enum everett { flanders, glisan, hoyt }
enum irving { johnson, kearney, lovejoy }
enum marshall { northrup, overton }
}
import alder::*;
fn main() {
let quimby: everett = glisan;
}
}

View File

@ -1,21 +1,21 @@
// xfail-test
import alder::*;
mod alder {
export burnside;
export everett::{flanders};
export irving::{johnson, kearney};
export marshall::{};
tag burnside { couch, davis }
tag everett { flanders, glisan, hoyt }
tag irving { johnson, kearney, lovejoy }
tag marshall { northrup, overton }
enum burnside { couch, davis }
enum everett { flanders, glisan, hoyt }
enum irving { johnson, kearney, lovejoy }
enum marshall { northrup, overton }
}
import alder::*;
fn main() {
let pettygrove: burnside = couch;
let quimby: everett = flanders;
let raleigh: irving = johnson;
let savier: marshall;
}
let _pettygrove: burnside = couch;
let _quimby: everett = flanders;
let _raleigh: irving = johnson;
let _savier: marshall;
}