Encode meta tags in the crate and start sketching enhanced logic for resolving crate "use" directives.

Now with extra "works on OSX" kludging.
This commit is contained in:
Graydon Hoare 2011-06-10 12:56:42 -07:00
parent 4634f236a9
commit 52c4c9014f
8 changed files with 176 additions and 48 deletions

View file

@ -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 {

View file

@ -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,

View file

@ -506,24 +506,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;
}
@ -541,8 +592,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 {

View file

@ -1976,20 +1976,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;
@ -2178,7 +2184,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 (_) {

View file

@ -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.
@ -717,12 +724,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);

View file

@ -1009,7 +1009,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);

View file

@ -1,22 +1,33 @@
native "rust" mod rustrt {
fn rust_list_files(str path) -> vec[str];
fn rust_dirent_filename(os::libc::dirent ent) -> str;
}
fn list_dir(str path) -> vec[str] {
ret rustrt::rust_list_files(path);
// TODO ensure this is always closed
// FIXME: No idea why, but this appears to corrupt memory on OSX. I suspect
// it has to do with the tasking primitives somehow, or perhaps the
// FFI. Worth investigating more when we're digging into the FFI and unsafe
// mode in more detail; in the meantime we just call list_files above and
// skip this code.
/*
auto dir = os::libc::opendir(str::buf(path));
assert (dir as uint != 0u);
let vec[str] result = [];
while (true) {
auto ent = os::libc::readdir(dir);
if (ent as int == 0) {
os::libc::closedir(dir);
ret result;
}
vec::push[str](result, rustrt::rust_dirent_filename(ent));
auto ent = os::libc::readdir(dir);
if (ent as int == 0) {
os::libc::closedir(dir);
ret result;
}
vec::push[str](result, rustrt::rust_dirent_filename(ent));
}
os::libc::closedir(dir);
ret result;
*/
}
const char path_sep = '/';

View file

@ -486,8 +486,8 @@ rust_str* c_str_to_rust(rust_task *task, char const *str) {
extern "C" CDECL rust_vec*
rust_list_files(rust_task *task, rust_str *path) {
#if defined(__WIN32__)
array_list<rust_str*> strings;
#if defined(__WIN32__)
WIN32_FIND_DATA FindFileData;
HANDLE hFind = FindFirstFile((char*)path->data, &FindFileData);
if (hFind != INVALID_HANDLE_VALUE) {
@ -496,11 +496,17 @@ rust_list_files(rust_task *task, rust_str *path) {
} while (FindNextFile(hFind, &FindFileData));
FindClose(hFind);
}
return vec_alloc_with_data(task, strings.size(), strings.size(),
sizeof(rust_str*), strings.data());
#else
return NULL;
DIR *dirp = opendir((char*)path->data);
if (dirp) {
struct dirent *dp;
while ((dp = readdir(dirp)))
strings.push(c_str_to_rust(task, dp->d_name));
closedir(dirp);
}
#endif
return vec_alloc_with_data(task, strings.size(), strings.size(),
sizeof(rust_str*), strings.data());
}
#if defined(__WIN32__)
@ -562,6 +568,6 @@ get_time(rust_task *task, uint32_t *sec, uint32_t *usec) {
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// compile-command: "make -k -C .. 2>&1 | sed -e 's/\\/x\\//x:\\//g'";
// compile-command: "make -k -C $RBUILD 2>&1 | sed -e 's/\\/x\\//x:\\//g'";
// End:
//