Skip to content

Commit 52c4c90

Browse files
committed
Encode meta tags in the crate and start sketching enhanced logic for resolving crate "use" directives.
Now with extra "works on OSX" kludging.
1 parent 4634f23 commit 52c4c90

File tree

8 files changed

+175
-47
lines changed

8 files changed

+175
-47
lines changed

src/comp/back/link.rs

Lines changed: 31 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -279,7 +279,7 @@ mod write {
279279
*/
280280

281281

282-
iter crate_export_metas(ast::crate c) -> @ast::meta_item {
282+
iter crate_export_metas(&ast::crate c) -> @ast::meta_item {
283283
for (@ast::crate_directive cdir in c.node.directives) {
284284
alt (cdir.node) {
285285
case (ast::cdir_meta(?v, ?mis)) {
@@ -293,12 +293,30 @@ iter crate_export_metas(ast::crate c) -> @ast::meta_item {
293293
}
294294
}
295295
}
296-
fn get_crate_meta(&session::session sess,
297-
&ast::crate c, str k, str default,
298-
bool warn_default) -> str {
296+
297+
298+
iter crate_local_metas(&ast::crate c) -> @ast::meta_item {
299+
for (@ast::crate_directive cdir in c.node.directives) {
300+
alt (cdir.node) {
301+
case (ast::cdir_meta(?v, ?mis)) {
302+
if (v == ast::local_meta) {
303+
for (@ast::meta_item mi in mis) {
304+
put mi;
305+
}
306+
}
307+
}
308+
case (_) {}
309+
}
310+
}
311+
}
312+
313+
314+
fn get_crate_meta_export(&session::session sess,
315+
&ast::crate c, str k, str default,
316+
bool warn_default) -> str {
299317
let vec[@ast::meta_item] v = [];
300318
for each (@ast::meta_item mi in crate_export_metas(c)) {
301-
if (mi.node.name == k) {
319+
if (mi.node.key == k) {
302320
v += [mi];
303321
}
304322
}
@@ -323,7 +341,7 @@ fn get_crate_meta(&session::session sess,
323341
fn crate_meta_extras_hash(sha1 sha, &ast::crate crate) -> str {
324342
fn lteq(&@ast::meta_item ma,
325343
&@ast::meta_item mb) -> bool {
326-
ret ma.node.name <= mb.node.name;
344+
ret ma.node.key <= mb.node.key;
327345
}
328346

329347
fn len_and_str(&str s) -> str {
@@ -332,16 +350,16 @@ fn crate_meta_extras_hash(sha1 sha, &ast::crate crate) -> str {
332350

333351
let vec[mutable @ast::meta_item] v = [mutable];
334352
for each (@ast::meta_item mi in crate_export_metas(crate)) {
335-
if (mi.node.name != "name" &&
336-
mi.node.name != "vers") {
353+
if (mi.node.key != "name" &&
354+
mi.node.key != "vers") {
337355
v += [mutable mi];
338356
}
339357
}
340358
sort::quick_sort(lteq, v);
341359
sha.reset();
342360
for (@ast::meta_item m_ in v) {
343361
auto m = m_;
344-
sha.input_str(len_and_str(m.node.name));
362+
sha.input_str(len_and_str(m.node.key));
345363
sha.input_str(len_and_str(m.node.value));
346364
}
347365
ret truncated_sha1_result(sha);
@@ -352,13 +370,13 @@ fn crate_meta_name(&session::session sess, &ast::crate crate,
352370
auto os = str::split(fs::basename(output), '.' as u8);
353371
assert vec::len(os) >= 2u;
354372
vec::pop(os);
355-
ret get_crate_meta(sess, crate, "name", str::connect(os, "."),
356-
sess.get_opts().shared);
373+
ret get_crate_meta_export(sess, crate, "name", str::connect(os, "."),
374+
sess.get_opts().shared);
357375
}
358376

359377
fn crate_meta_vers(&session::session sess, &ast::crate crate) -> str {
360-
ret get_crate_meta(sess, crate, "vers", "0.0",
361-
sess.get_opts().shared);
378+
ret get_crate_meta_export(sess, crate, "vers", "0.0",
379+
sess.get_opts().shared);
362380
}
363381

364382
fn truncated_sha1_result(sha1 sha) -> str {

src/comp/front/ast.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ type crate_directive = spanned[crate_directive_];
9797

9898

9999
type meta_item = spanned[meta_item_];
100-
type meta_item_ = rec(ident name, str value);
100+
type meta_item_ = rec(ident key, str value);
101101

102102
type block = spanned[block_];
103103
type block_ = rec(vec[@stmt] stmts,

src/comp/front/creader.rs

Lines changed: 67 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -506,24 +506,75 @@ fn get_metadata_section(str filename) -> option::t[vec[u8]] {
506506
}
507507

508508

509-
fn load_crate(session::session sess,
510-
int cnum,
511-
ast::ident ident,
512-
vec[str] library_search_paths) {
513-
auto filename = parser::default_native_name(sess, ident);
509+
fn metadata_matches(&vec[u8] data,
510+
&vec[@ast::meta_item] metas) -> bool {
511+
ret true;
512+
}
513+
514+
fn find_library_crate(&session::session sess,
515+
&ast::ident ident,
516+
&vec[@ast::meta_item] metas,
517+
&vec[str] library_search_paths)
518+
-> option::t[tup(str, vec[u8])] {
519+
520+
let str crate_name = ident;
521+
for (@ast::meta_item mi in metas) {
522+
if (mi.node.key == "name") {
523+
crate_name = mi.node.value;
524+
break;
525+
}
526+
}
527+
auto nn = parser::default_native_lib_naming(sess);
528+
let str prefix = nn.prefix + crate_name;
529+
530+
// FIXME: we could probably use a 'glob' function in std::fs but it will
531+
// be much easier to write once the unsafe module knows more about FFI
532+
// tricks. Currently the glob(3) interface is a bit more than we can
533+
// stomach from here, and writing a C++ wrapper is more work than just
534+
// manually filtering fs::list_dir here.
535+
514536
for (str library_search_path in library_search_paths) {
515-
auto path = fs::connect(library_search_path, filename);
516-
alt (get_metadata_section(path)) {
517-
case (option::some(?cvec)) {
518-
sess.set_external_crate(cnum, rec(name=ident, data=cvec));
519-
ret;
537+
538+
for (str path in fs::list_dir(library_search_path)) {
539+
540+
let str f = fs::basename(path);
541+
if (! (str::starts_with(f, prefix) &&
542+
str::ends_with(f, nn.suffix))) {
543+
log #fmt("skipping %s, doesn't look like %s*%s",
544+
path, prefix, nn.suffix);
545+
cont;
546+
}
547+
548+
alt (get_metadata_section(path)) {
549+
case (option::some(?cvec)) {
550+
if (!metadata_matches(cvec, metas)) {
551+
log #fmt("skipping %s, metadata doesn't match", path);
552+
cont;
553+
}
554+
log #fmt("found %s with matching metadata", path);
555+
ret some(tup(path, cvec));
556+
}
557+
case (_) {}
520558
}
521-
case (_) {}
522559
}
523560
}
524-
525-
log_err #fmt("can't open crate '%s' (looked for '%s' in lib search path)",
526-
ident, filename);
561+
ret none;
562+
}
563+
564+
fn load_library_crate(&session::session sess,
565+
&int cnum,
566+
&ast::ident ident,
567+
&vec[@ast::meta_item] metas,
568+
&vec[str] library_search_paths) {
569+
alt (find_library_crate(sess, ident, metas, library_search_paths)) {
570+
case (some(?t)) {
571+
sess.set_external_crate(cnum, rec(name=ident,
572+
data=t._1));
573+
ret;
574+
}
575+
case (_) {}
576+
}
577+
log_err #fmt("can't find crate for '%s'", ident);
527578
fail;
528579
}
529580

@@ -541,8 +592,8 @@ fn visit_view_item(env e, &@ast::view_item i) {
541592
auto cnum;
542593
if (!e.crate_cache.contains_key(ident)) {
543594
cnum = e.next_crate_num;
544-
load_crate(e.sess, cnum, ident,
545-
e.library_search_paths);
595+
load_library_crate(e.sess, cnum, ident, meta_items,
596+
e.library_search_paths);
546597
e.crate_cache.insert(ident, e.next_crate_num);
547598
e.next_crate_num += 1;
548599
} else {

src/comp/front/parser.rs

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1976,20 +1976,26 @@ fn parse_native_mod_items(&parser p, &str native_name,
19761976
items=items);
19771977
}
19781978

1979-
fn default_native_name(session::session sess, str id) -> str {
1979+
fn default_native_lib_naming(session::session sess)
1980+
-> rec(str prefix, str suffix) {
19801981
alt (sess.get_targ_cfg().os) {
19811982
case (session::os_win32) {
1982-
ret id + ".dll";
1983+
ret rec(prefix="", suffix=".dll");
19831984
}
19841985
case (session::os_macos) {
1985-
ret "lib" + id + ".dylib";
1986+
ret rec(prefix="lib", suffix=".dylib");
19861987
}
19871988
case (session::os_linux) {
1988-
ret "lib" + id + ".so";
1989+
ret rec(prefix="lib", suffix=".so");
19891990
}
19901991
}
19911992
}
19921993

1994+
fn default_native_name(session::session sess, str id) -> str {
1995+
auto n = default_native_lib_naming(sess);
1996+
ret n.prefix + id + n.suffix;
1997+
}
1998+
19931999
fn parse_item_native_mod(&parser p) -> @ast::item {
19942000
auto lo = p.get_last_lo_pos();
19952001
auto abi = ast::native_abi_cdecl;
@@ -2178,7 +2184,7 @@ fn parse_meta_item(&parser p) -> @ast::meta_item {
21782184
case (token::LIT_STR(?s)) {
21792185
auto hi = p.get_hi_pos();
21802186
p.bump();
2181-
ret @spanned(lo, hi, rec(name = ident,
2187+
ret @spanned(lo, hi, rec(key = ident,
21822188
value = p.get_str(s)));
21832189
}
21842190
case (_) {

src/comp/middle/metadata.rs

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import middle::trans;
1414
import middle::ty;
1515
import middle::ty::path_to_str;
1616
import back::x86;
17+
import back::link;
1718
import util::common;
1819
import pretty::ppaux::lit_to_str;
1920

@@ -46,6 +47,12 @@ const uint tag_index_buckets_bucket = 0x13u;
4647
const uint tag_index_buckets_bucket_elt = 0x14u;
4748
const uint tag_index_table = 0x15u;
4849

50+
const uint tag_meta_export = 0x16u;
51+
const uint tag_meta_local = 0x17u;
52+
const uint tag_meta_item = 0x18u;
53+
const uint tag_meta_item_key = 0x19u;
54+
const uint tag_meta_item_value = 0x20u;
55+
4956
// Type encoding
5057

5158
// 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) {
717724
}
718725

719726

727+
fn encode_meta_items(&ebml::writer ebml_w, &ast::crate crate) {
728+
729+
fn encode_meta_item(&ebml::writer ebml_w, &ast::meta_item mi) {
730+
ebml::start_tag(ebml_w, tag_meta_item);
731+
ebml::start_tag(ebml_w, tag_meta_item_key);
732+
ebml_w.writer.write(str::bytes(mi.node.key));
733+
ebml::end_tag(ebml_w);
734+
ebml::start_tag(ebml_w, tag_meta_item_value);
735+
ebml_w.writer.write(str::bytes(mi.node.value));
736+
ebml::end_tag(ebml_w);
737+
ebml::end_tag(ebml_w);
738+
}
739+
740+
ebml::start_tag(ebml_w, tag_meta_export);
741+
for each (@ast::meta_item mi in link::crate_export_metas(crate)) {
742+
encode_meta_item(ebml_w, *mi);
743+
}
744+
ebml::end_tag(ebml_w);
745+
746+
ebml::start_tag(ebml_w, tag_meta_local);
747+
for each (@ast::meta_item mi in link::crate_local_metas(crate)) {
748+
encode_meta_item(ebml_w, *mi);
749+
}
750+
ebml::end_tag(ebml_w);
751+
}
752+
720753
fn encode_metadata(&@trans::crate_ctxt cx, &@ast::crate crate)
721754
-> ValueRef {
722755
auto string_w = io::string_writer();
723756
auto buf_w = string_w.get_writer().get_buf_writer();
724757
auto ebml_w = ebml::create_writer(buf_w);
725758

759+
// Encode the meta items
760+
encode_meta_items(ebml_w, *crate);
761+
726762
// Encode and index the paths.
727763
ebml::start_tag(ebml_w, tag_paths);
728764
auto paths_index = encode_item_paths(ebml_w, crate);

src/comp/pretty/pprust.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1009,7 +1009,7 @@ fn print_view_item(&ps s, &@ast::view_item item) {
10091009
popen(s);
10101010
fn print_meta(&ps s, &@ast::meta_item item) {
10111011
ibox(s, indent_unit);
1012-
word_space(s, item.node.name);
1012+
word_space(s, item.node.key);
10131013
word_space(s, "=");
10141014
print_string(s, item.node.value);
10151015
end(s);

src/lib/posix_fs.rs

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,33 @@
11
native "rust" mod rustrt {
2+
fn rust_list_files(str path) -> vec[str];
23
fn rust_dirent_filename(os::libc::dirent ent) -> str;
34
}
45

56
fn list_dir(str path) -> vec[str] {
7+
ret rustrt::rust_list_files(path);
68
// TODO ensure this is always closed
9+
10+
// FIXME: No idea why, but this appears to corrupt memory on OSX. I suspect
11+
// it has to do with the tasking primitives somehow, or perhaps the
12+
// FFI. Worth investigating more when we're digging into the FFI and unsafe
13+
// mode in more detail; in the meantime we just call list_files above and
14+
// skip this code.
15+
16+
/*
717
auto dir = os::libc::opendir(str::buf(path));
818
assert (dir as uint != 0u);
919
let vec[str] result = [];
1020
while (true) {
11-
auto ent = os::libc::readdir(dir);
12-
if (ent as int == 0) {
13-
os::libc::closedir(dir);
14-
ret result;
15-
}
16-
vec::push[str](result, rustrt::rust_dirent_filename(ent));
21+
auto ent = os::libc::readdir(dir);
22+
if (ent as int == 0) {
23+
os::libc::closedir(dir);
24+
ret result;
25+
}
26+
vec::push[str](result, rustrt::rust_dirent_filename(ent));
1727
}
1828
os::libc::closedir(dir);
1929
ret result;
30+
*/
2031
}
2132

2233
const char path_sep = '/';

src/rt/rust_builtin.cpp

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -486,8 +486,8 @@ rust_str* c_str_to_rust(rust_task *task, char const *str) {
486486

487487
extern "C" CDECL rust_vec*
488488
rust_list_files(rust_task *task, rust_str *path) {
489-
#if defined(__WIN32__)
490489
array_list<rust_str*> strings;
490+
#if defined(__WIN32__)
491491
WIN32_FIND_DATA FindFileData;
492492
HANDLE hFind = FindFirstFile((char*)path->data, &FindFileData);
493493
if (hFind != INVALID_HANDLE_VALUE) {
@@ -496,11 +496,17 @@ rust_list_files(rust_task *task, rust_str *path) {
496496
} while (FindNextFile(hFind, &FindFileData));
497497
FindClose(hFind);
498498
}
499-
return vec_alloc_with_data(task, strings.size(), strings.size(),
500-
sizeof(rust_str*), strings.data());
501499
#else
502-
return NULL;
500+
DIR *dirp = opendir((char*)path->data);
501+
if (dirp) {
502+
struct dirent *dp;
503+
while ((dp = readdir(dirp)))
504+
strings.push(c_str_to_rust(task, dp->d_name));
505+
closedir(dirp);
506+
}
503507
#endif
508+
return vec_alloc_with_data(task, strings.size(), strings.size(),
509+
sizeof(rust_str*), strings.data());
504510
}
505511

506512
#if defined(__WIN32__)
@@ -562,6 +568,6 @@ get_time(rust_task *task, uint32_t *sec, uint32_t *usec) {
562568
// indent-tabs-mode: nil
563569
// c-basic-offset: 4
564570
// buffer-file-coding-system: utf-8-unix
565-
// compile-command: "make -k -C .. 2>&1 | sed -e 's/\\/x\\//x:\\//g'";
571+
// compile-command: "make -k -C $RBUILD 2>&1 | sed -e 's/\\/x\\//x:\\//g'";
566572
// End:
567573
//

0 commit comments

Comments
 (0)