rustc: Introduce and parse additional meta_item forms

Examples: #[test], #[link(name = "vers")]

Issue #487
This commit is contained in:
Brian Anderson 2011-06-21 14:23:16 -07:00
parent 64513808ca
commit adc18bb24a
8 changed files with 153 additions and 37 deletions

View file

@ -291,7 +291,15 @@ fn get_crate_meta_export(&session::session sess, &ast::crate c, str k,
str default, bool warn_default) -> str {
let vec[@ast::meta_item] v = [];
for each (@ast::meta_item mi in crate_export_metas(c)) {
if (mi.node.key == k) { v += [mi]; }
// FIXME (#487): Support all variants of meta_item
alt (mi.node) {
case (ast::meta_key_value(?key, ?value)) {
if (key == k) { v += [mi]; }
}
case (_) {
sess.unimpl("meta_item variant");
}
}
}
alt (vec::len(v)) {
case (0u) {
@ -301,7 +309,16 @@ fn get_crate_meta_export(&session::session sess, &ast::crate c, str k,
}
ret default;
}
case (1u) { ret v.(0).node.value; }
case (1u) {
alt (v.(0).node) {
case (ast::meta_key_value(_, ?value)) {
ret value;
}
case (_) {
sess.unimpl("meta_item variant");
}
}
}
case (_) {
sess.span_fatal(v.(1).span, #fmt("duplicate meta '%s'", k));
}
@ -312,21 +329,45 @@ fn get_crate_meta_export(&session::session sess, &ast::crate c, str k,
// This calculates CMH as defined above
fn crate_meta_extras_hash(sha1 sha, &ast::crate crate) -> str {
fn lteq(&@ast::meta_item ma, &@ast::meta_item mb) -> bool {
ret ma.node.key <= mb.node.key;
fn key(&@ast::meta_item m) -> ast::ident {
alt (m.node) {
case (ast::meta_word(?name)) {
name
}
case (ast::meta_key_value(?key, _)) {
key
}
}
}
ret key(ma) <= key(mb);
}
fn len_and_str(&str s) -> str { ret #fmt("%u_%s", str::byte_len(s), s); }
let vec[mutable @ast::meta_item] v = [mutable ];
for each (@ast::meta_item mi in crate_export_metas(crate)) {
if (mi.node.key != "name" && mi.node.key != "vers") {
v += [mutable mi];
alt (mi.node) {
case (ast::meta_key_value(?key, _)) {
if (key != "name" && key != "vers") {
v += [mutable mi];
}
}
case (_) {
v += [mutable mi];
}
}
}
sort::quick_sort(lteq, v);
sha.reset();
for (@ast::meta_item m_ in v) {
auto m = m_;
sha.input_str(len_and_str(m.node.key));
sha.input_str(len_and_str(m.node.value));
alt (m.node) {
case (ast::meta_key_value(?key, ?value)) {
sha.input_str(len_and_str(key));
sha.input_str(len_and_str(value));
}
case (ast::meta_word(?name)) {
sha.input_str(len_and_str(name));
}
}
}
ret truncated_sha1_result(sha);
}

View file

@ -97,7 +97,11 @@ type crate_directive = spanned[crate_directive_];
type meta_item = spanned[meta_item_];
type meta_item_ = rec(ident key, str value);
tag meta_item_ {
meta_word(ident);
meta_list(ident, vec[@meta_item]);
meta_key_value(ident, str);
}
type block = spanned[block_];

View file

@ -548,19 +548,30 @@ fn metadata_matches(hashmap[str, str] mm, &vec[@ast::meta_item] metas) ->
log #fmt("matching %u metadata requirements against %u metadata items",
vec::len(metas), mm.size());
for (@ast::meta_item mi in metas) {
alt (mm.find(mi.node.key)) {
case (some(?v)) {
if (v == mi.node.value) {
log #fmt("matched '%s': '%s'", mi.node.key,
mi.node.value);
} else {
log #fmt("missing '%s': '%s' (got '%s')", mi.node.key,
mi.node.value, v);
ret false;
alt (mi.node) {
case (ast::meta_key_value(?key, ?value)) {
alt (mm.find(key)) {
case (some(?v)) {
if (v == value) {
log #fmt("matched '%s': '%s'", key,
value);
} else {
log #fmt("missing '%s': '%s' (got '%s')",
key,
value, v);
ret false;
}
}
case (none) {
log #fmt("missing '%s': '%s'",
key, value);
ret false;
}
}
}
case (none) {
log #fmt("missing '%s': '%s'", mi.node.key, mi.node.value);
case (_) {
// FIXME (#487): Support all forms of meta_item
log_err "unimplemented meta_item variant in metadata_matches";
ret false;
}
}
@ -574,7 +585,18 @@ fn find_library_crate(&session::session sess, &ast::ident ident,
option::t[tup(str, vec[u8])] {
let str crate_name = ident;
for (@ast::meta_item mi in metas) {
if (mi.node.key == "name") { crate_name = mi.node.value; break; }
alt (mi.node) {
case (ast::meta_key_value(?key, ?value)) {
if (key == "name") {
crate_name = value;
break;
}
}
case (_) {
// FIXME (#487)
sess.unimpl("meta_item variant")
}
}
}
auto nn = parser::default_native_lib_naming(sess);
let str prefix = nn.prefix + crate_name;

View file

@ -2113,26 +2113,41 @@ fn parse_inner_attrs(&parser p) -> vec[ast::attribute] {
fn parse_meta_item(&parser p) -> @ast::meta_item {
auto lo = p.get_lo_pos();
auto ident = parse_ident(p);
expect(p, token::EQ);
alt (p.peek()) {
case (token::LIT_STR(?s)) {
auto hi = p.get_hi_pos();
case (token::EQ) {
p.bump();
ret @spanned(lo, hi, rec(key=ident, value=p.get_str(s)));
alt (p.peek()) {
case (token::LIT_STR(?s)) {
p.bump();
auto value = p.get_str(s);
auto hi = p.get_hi_pos();
ret @spanned(lo, hi, ast::meta_key_value(ident, value));
}
case (_) {
p.fatal("Metadata items must be string literals");
}
}
}
case (token::LPAREN) {
auto inner_items = parse_meta_seq(p);
auto hi = p.get_hi_pos();
ret @spanned(lo, hi, ast::meta_list(ident, inner_items));
}
case (_) {
auto hi = p.get_hi_pos();
ret @spanned(lo, hi, ast::meta_word(ident));
}
case (_) { p.fatal("Metadata items must be string literals"); }
}
fail;
}
fn parse_meta(&parser p) -> vec[@ast::meta_item] {
fn parse_meta_seq(&parser p) -> vec[@ast::meta_item] {
ret parse_seq(token::LPAREN, token::RPAREN, some(token::COMMA),
parse_meta_item, p).node;
}
fn parse_optional_meta(&parser p) -> vec[@ast::meta_item] {
alt (p.peek()) {
case (token::LPAREN) { ret parse_meta(p); }
case (token::LPAREN) { ret parse_meta_seq(p); }
case (_) { let vec[@ast::meta_item] v = []; ret v; }
}
}

View file

@ -669,13 +669,21 @@ fn write_int(&io::writer writer, &int n) {
fn encode_meta_items(&ebml::writer ebml_w, &crate crate) {
fn encode_meta_item(&ebml::writer ebml_w, &meta_item mi) {
// FIXME (#487): Support all forms of meta item
ebml::start_tag(ebml_w, tag_meta_item);
ebml::start_tag(ebml_w, tag_meta_item_key);
ebml_w.writer.write(str::bytes(mi.node.key));
ebml::end_tag(ebml_w);
ebml::start_tag(ebml_w, tag_meta_item_value);
ebml_w.writer.write(str::bytes(mi.node.value));
ebml::end_tag(ebml_w);
alt (mi.node) {
case (meta_key_value(?key, ?value)) {
ebml::start_tag(ebml_w, tag_meta_item_key);
ebml_w.writer.write(str::bytes(key));
ebml::end_tag(ebml_w);
ebml::start_tag(ebml_w, tag_meta_item_value);
ebml_w.writer.write(str::bytes(value));
ebml::end_tag(ebml_w);
}
case (_) {
log_err "unimplemented meta_item type";
}
}
ebml::end_tag(ebml_w);
}
ebml::start_tag(ebml_w, tag_meta_export);

View file

@ -1018,9 +1018,18 @@ fn print_type_params(&ps s, &vec[ast::ty_param] params) {
fn print_meta_item(&ps s, &@ast::meta_item item) {
ibox(s, indent_unit);
word_space(s, item.node.key);
word_space(s, "=");
print_string(s, item.node.value);
// FIXME (#487): Print other meta item variants
alt (item.node) {
case (ast::meta_key_value(?key, ?value)) {
word_space(s, key);
word_space(s, "=");
print_string(s, value);
}
case (_) {
log_err "unimplemented meta_item variant";
fail;
}
}
end(s);
}

View file

@ -0,0 +1,6 @@
// xfail-stage0
// error-pattern:expecting \]
// asterisk is bogus
#[attr*]
mod m { }

View file

@ -173,6 +173,17 @@ mod test_distinguish_syntax_ext {
}
}
mod test_other_forms {
#[attr]
#[attr(word)]
#[attr(attr(word))]
#[attr(key1 = "val",
key2 = "val",
attr)]
fn f() {
}
}
fn main() {
}