From ab3635eebef2b8cf0e19cdbc5b4e8dd7a49a4658 Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Thu, 9 Jun 2011 17:24:25 -0700 Subject: [PATCH] Encode meta tags in the crate and start sketching enhanced logic for resolving crate "use" directives. --- src/comp/back/link.rs | 44 +++++++++++++------ src/comp/front/ast.rs | 2 +- src/comp/front/creader.rs | 85 +++++++++++++++++++++++++++++-------- src/comp/front/parser.rs | 16 ++++--- src/comp/middle/metadata.rs | 36 ++++++++++++++++ src/comp/pretty/pprust.rs | 2 +- 6 files changed, 148 insertions(+), 37 deletions(-) diff --git a/src/comp/back/link.rs b/src/comp/back/link.rs index 202b963bd60..d21969476a7 100644 --- a/src/comp/back/link.rs +++ b/src/comp/back/link.rs @@ -279,7 +279,7 @@ mod write { */ -iter crate_export_metas(ast::crate c) -> @ast::meta_item { +iter crate_export_metas(&ast::crate c) -> @ast::meta_item { for (@ast::crate_directive cdir in c.node.directives) { alt (cdir.node) { case (ast::cdir_meta(?v, ?mis)) { @@ -293,12 +293,30 @@ iter crate_export_metas(ast::crate c) -> @ast::meta_item { } } } -fn get_crate_meta(&session::session sess, - &ast::crate c, str k, str default, - bool warn_default) -> str { + + +iter crate_local_metas(&ast::crate c) -> @ast::meta_item { + for (@ast::crate_directive cdir in c.node.directives) { + alt (cdir.node) { + case (ast::cdir_meta(?v, ?mis)) { + if (v == ast::local_meta) { + for (@ast::meta_item mi in mis) { + put mi; + } + } + } + case (_) {} + } + } +} + + +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.name == k) { + if (mi.node.key == k) { v += [mi]; } } @@ -323,7 +341,7 @@ fn get_crate_meta(&session::session sess, 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.name <= mb.node.name; + ret ma.node.key <= mb.node.key; } fn len_and_str(&str s) -> str { @@ -332,8 +350,8 @@ fn crate_meta_extras_hash(sha1 sha, &ast::crate crate) -> str { let vec[mutable @ast::meta_item] v = [mutable]; for each (@ast::meta_item mi in crate_export_metas(crate)) { - if (mi.node.name != "name" && - mi.node.name != "vers") { + if (mi.node.key != "name" && + mi.node.key != "vers") { v += [mutable mi]; } } @@ -341,7 +359,7 @@ fn crate_meta_extras_hash(sha1 sha, &ast::crate crate) -> str { sha.reset(); for (@ast::meta_item m_ in v) { auto m = m_; - sha.input_str(len_and_str(m.node.name)); + sha.input_str(len_and_str(m.node.key)); sha.input_str(len_and_str(m.node.value)); } ret truncated_sha1_result(sha); @@ -352,13 +370,13 @@ fn crate_meta_name(&session::session sess, &ast::crate crate, auto os = str::split(fs::basename(output), '.' as u8); assert vec::len(os) >= 2u; vec::pop(os); - ret get_crate_meta(sess, crate, "name", str::connect(os, "."), - sess.get_opts().shared); + ret get_crate_meta_export(sess, crate, "name", str::connect(os, "."), + sess.get_opts().shared); } fn crate_meta_vers(&session::session sess, &ast::crate crate) -> str { - ret get_crate_meta(sess, crate, "vers", "0.0", - sess.get_opts().shared); + ret get_crate_meta_export(sess, crate, "vers", "0.0", + sess.get_opts().shared); } fn truncated_sha1_result(sha1 sha) -> str { diff --git a/src/comp/front/ast.rs b/src/comp/front/ast.rs index b36a956464c..fd0fd7f0193 100644 --- a/src/comp/front/ast.rs +++ b/src/comp/front/ast.rs @@ -97,7 +97,7 @@ type crate_directive = spanned[crate_directive_]; type meta_item = spanned[meta_item_]; -type meta_item_ = rec(ident name, str value); +type meta_item_ = rec(ident key, str value); type block = spanned[block_]; type block_ = rec(vec[@stmt] stmts, diff --git a/src/comp/front/creader.rs b/src/comp/front/creader.rs index e0be9606384..d9dad04db92 100644 --- a/src/comp/front/creader.rs +++ b/src/comp/front/creader.rs @@ -500,24 +500,75 @@ fn get_metadata_section(str filename) -> option::t[vec[u8]] { } -fn load_crate(session::session sess, - int cnum, - ast::ident ident, - vec[str] library_search_paths) { - auto filename = parser::default_native_name(sess, ident); - for (str library_search_path in library_search_paths) { - auto path = fs::connect(library_search_path, filename); - alt (get_metadata_section(path)) { - case (option::some(?cvec)) { - sess.set_external_crate(cnum, rec(name=ident, data=cvec)); - ret; - } - case (_) {} +fn metadata_matches(&vec[u8] data, + &vec[@ast::meta_item] metas) -> bool { + ret true; +} + +fn find_library_crate(&session::session sess, + &ast::ident ident, + &vec[@ast::meta_item] metas, + &vec[str] library_search_paths) + -> 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; } } + auto nn = parser::default_native_lib_naming(sess); + let str prefix = nn.prefix + crate_name; - log_err #fmt("can't open crate '%s' (looked for '%s' in lib search path)", - ident, filename); + // FIXME: we could probably use a 'glob' function in std::fs but it will + // be much easier to write once the unsafe module knows more about FFI + // tricks. Currently the glob(3) interface is a bit more than we can + // stomach from here, and writing a C++ wrapper is more work than just + // manually filtering fs::list_dir here. + + for (str library_search_path in library_search_paths) { + + for (str path in fs::list_dir(library_search_path)) { + + let str f = fs::basename(path); + if (! (str::starts_with(f, prefix) && + str::ends_with(f, nn.suffix))) { + log #fmt("skipping %s, doesn't look like %s*%s", + path, prefix, nn.suffix); + cont; + } + + alt (get_metadata_section(path)) { + case (option::some(?cvec)) { + if (!metadata_matches(cvec, metas)) { + log #fmt("skipping %s, metadata doesn't match", path); + cont; + } + log #fmt("found %s with matching metadata", path); + ret some(tup(path, cvec)); + } + case (_) {} + } + } + } + ret none; +} + +fn load_library_crate(&session::session sess, + &int cnum, + &ast::ident ident, + &vec[@ast::meta_item] metas, + &vec[str] library_search_paths) { + alt (find_library_crate(sess, ident, metas, library_search_paths)) { + case (some(?t)) { + sess.set_external_crate(cnum, rec(name=ident, + data=t._1)); + ret; + } + case (_) {} + } + log_err #fmt("can't find crate for '%s'", ident); fail; } @@ -535,8 +586,8 @@ fn visit_view_item(env e, &@ast::view_item i) { auto cnum; if (!e.crate_cache.contains_key(ident)) { cnum = e.next_crate_num; - load_crate(e.sess, cnum, ident, - e.library_search_paths); + load_library_crate(e.sess, cnum, ident, meta_items, + e.library_search_paths); e.crate_cache.insert(ident, e.next_crate_num); e.next_crate_num += 1; } else { diff --git a/src/comp/front/parser.rs b/src/comp/front/parser.rs index d3a8fa9a329..666df9d8eb3 100644 --- a/src/comp/front/parser.rs +++ b/src/comp/front/parser.rs @@ -1992,20 +1992,26 @@ fn parse_native_mod_items(&parser p, &str native_name, items=items); } -fn default_native_name(session::session sess, str id) -> str { +fn default_native_lib_naming(session::session sess) + -> rec(str prefix, str suffix) { alt (sess.get_targ_cfg().os) { case (session::os_win32) { - ret id + ".dll"; + ret rec(prefix="", suffix=".dll"); } case (session::os_macos) { - ret "lib" + id + ".dylib"; + ret rec(prefix="lib", suffix=".dylib"); } case (session::os_linux) { - ret "lib" + id + ".so"; + ret rec(prefix="lib", suffix=".so"); } } } +fn default_native_name(session::session sess, str id) -> str { + auto n = default_native_lib_naming(sess); + ret n.prefix + id + n.suffix; +} + fn parse_item_native_mod(&parser p) -> @ast::item { auto lo = p.get_last_lo_pos(); auto abi = ast::native_abi_cdecl; @@ -2194,7 +2200,7 @@ fn parse_meta_item(&parser p) -> @ast::meta_item { case (token::LIT_STR(?s)) { auto hi = p.get_hi_pos(); p.bump(); - ret @spanned(lo, hi, rec(name = ident, + ret @spanned(lo, hi, rec(key = ident, value = p.get_str(s))); } case (_) { diff --git a/src/comp/middle/metadata.rs b/src/comp/middle/metadata.rs index 8322de5bc90..b6ce15a8ba8 100644 --- a/src/comp/middle/metadata.rs +++ b/src/comp/middle/metadata.rs @@ -14,6 +14,7 @@ import middle::trans; import middle::ty; import middle::ty::path_to_str; import back::x86; +import back::link; import util::common; import pretty::ppaux::lit_to_str; @@ -46,6 +47,12 @@ const uint tag_index_buckets_bucket = 0x13u; const uint tag_index_buckets_bucket_elt = 0x14u; const uint tag_index_table = 0x15u; +const uint tag_meta_export = 0x16u; +const uint tag_meta_local = 0x17u; +const uint tag_meta_item = 0x18u; +const uint tag_meta_item_key = 0x19u; +const uint tag_meta_item_value = 0x20u; + // Type encoding // Compact string representation for ty.t values. API ty_str & parse_from_str. @@ -709,12 +716,41 @@ fn write_int(&io::writer writer, &int n) { } +fn encode_meta_items(&ebml::writer ebml_w, &ast::crate crate) { + + fn encode_meta_item(&ebml::writer ebml_w, &ast::meta_item mi) { + 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); + ebml::end_tag(ebml_w); + } + + ebml::start_tag(ebml_w, tag_meta_export); + for each (@ast::meta_item mi in link::crate_export_metas(crate)) { + encode_meta_item(ebml_w, *mi); + } + ebml::end_tag(ebml_w); + + ebml::start_tag(ebml_w, tag_meta_local); + for each (@ast::meta_item mi in link::crate_local_metas(crate)) { + encode_meta_item(ebml_w, *mi); + } + ebml::end_tag(ebml_w); +} + fn encode_metadata(&@trans::crate_ctxt cx, &@ast::crate crate) -> ValueRef { auto string_w = io::string_writer(); auto buf_w = string_w.get_writer().get_buf_writer(); auto ebml_w = ebml::create_writer(buf_w); + // Encode the meta items + encode_meta_items(ebml_w, *crate); + // Encode and index the paths. ebml::start_tag(ebml_w, tag_paths); auto paths_index = encode_item_paths(ebml_w, crate); diff --git a/src/comp/pretty/pprust.rs b/src/comp/pretty/pprust.rs index 20fe17c48c0..a7cbffeca6b 100644 --- a/src/comp/pretty/pprust.rs +++ b/src/comp/pretty/pprust.rs @@ -1000,7 +1000,7 @@ fn print_view_item(&ps s, &@ast::view_item item) { popen(s); fn print_meta(&ps s, &@ast::meta_item item) { ibox(s, indent_unit); - word_space(s, item.node.name); + word_space(s, item.node.key); word_space(s, "="); print_string(s, item.node.value); end(s);