-
Notifications
You must be signed in to change notification settings - Fork 12.5k
/
cstore.rs
188 lines (159 loc) · 5.98 KB
/
cstore.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
// The crate store - a central repo for information collected about external
// crates and libraries
use std::map;
use std::map::HashMap;
use syntax::{ast, attr};
use syntax::parse::token::ident_interner;
export cstore;
export cnum_map;
export crate_metadata;
export mk_cstore;
export get_crate_data;
export set_crate_data;
export get_crate_hash;
export get_crate_vers;
export have_crate_data;
export iter_crate_data;
export add_used_crate_file;
export get_used_crate_files;
export add_used_library;
export get_used_libraries;
export add_used_link_args;
export get_used_link_args;
export add_use_stmt_cnum;
export find_use_stmt_cnum;
export get_dep_hashes;
export get_path;
// A map from external crate numbers (as decoded from some crate file) to
// local crate numbers (as generated during this session). Each external
// crate may refer to types in other external crates, and each has their
// own crate numbers.
type cnum_map = map::HashMap<ast::crate_num, ast::crate_num>;
// Multiple items may have the same def_id in crate metadata. They may be
// renamed imports or reexports. This map keeps the "real" module path
// and def_id.
type mod_path_map = map::HashMap<ast::def_id, @~str>;
type crate_metadata = @{name: ~str,
data: @~[u8],
cnum_map: cnum_map,
cnum: ast::crate_num};
// This is a bit of an experiment at encapsulating the data in cstore. By
// keeping all the data in a non-exported enum variant, it's impossible for
// other modules to access the cstore's private data. This could also be
// achieved with an obj, but at the expense of a vtable. Not sure if this is a
// good pattern or not.
enum cstore { private(cstore_private), }
type cstore_private =
@{metas: map::HashMap<ast::crate_num, crate_metadata>,
use_crate_map: use_crate_map,
mod_path_map: mod_path_map,
mut used_crate_files: ~[Path],
mut used_libraries: ~[~str],
mut used_link_args: ~[~str],
intr: ident_interner};
// Map from node_id's of local use statements to crate numbers
type use_crate_map = map::HashMap<ast::node_id, ast::crate_num>;
// Internal method to retrieve the data from the cstore
pure fn p(cstore: cstore) -> cstore_private {
match cstore { private(p) => p }
}
fn mk_cstore(intr: ident_interner) -> cstore {
let meta_cache = map::HashMap::<int,crate_metadata>();
let crate_map = map::HashMap::<int,ast::crate_num>();
let mod_path_map = HashMap();
return private(@{metas: meta_cache,
use_crate_map: crate_map,
mod_path_map: mod_path_map,
mut used_crate_files: ~[],
mut used_libraries: ~[],
mut used_link_args: ~[],
intr: intr});
}
fn get_crate_data(cstore: cstore, cnum: ast::crate_num) -> crate_metadata {
return p(cstore).metas.get(cnum);
}
fn get_crate_hash(cstore: cstore, cnum: ast::crate_num) -> ~str {
let cdata = get_crate_data(cstore, cnum);
return decoder::get_crate_hash(cdata.data);
}
fn get_crate_vers(cstore: cstore, cnum: ast::crate_num) -> ~str {
let cdata = get_crate_data(cstore, cnum);
return decoder::get_crate_vers(cdata.data);
}
fn set_crate_data(cstore: cstore, cnum: ast::crate_num,
data: crate_metadata) {
p(cstore).metas.insert(cnum, data);
for vec::each(decoder::get_crate_module_paths(cstore.intr, data)) |dp| {
let (did, path) = *dp;
let d = {crate: cnum, node: did.node};
p(cstore).mod_path_map.insert(d, @path);
}
}
fn have_crate_data(cstore: cstore, cnum: ast::crate_num) -> bool {
return p(cstore).metas.contains_key(cnum);
}
fn iter_crate_data(cstore: cstore, i: fn(ast::crate_num, crate_metadata)) {
for p(cstore).metas.each |k,v| { i(k, v);};
}
fn add_used_crate_file(cstore: cstore, lib: &Path) {
if !vec::contains(p(cstore).used_crate_files, copy *lib) {
vec::push(p(cstore).used_crate_files, copy *lib);
}
}
fn get_used_crate_files(cstore: cstore) -> ~[Path] {
return p(cstore).used_crate_files;
}
fn add_used_library(cstore: cstore, lib: ~str) -> bool {
assert lib != ~"";
if vec::contains(p(cstore).used_libraries, lib) { return false; }
vec::push(p(cstore).used_libraries, lib);
return true;
}
fn get_used_libraries(cstore: cstore) -> ~[~str] {
return p(cstore).used_libraries;
}
fn add_used_link_args(cstore: cstore, args: ~str) {
vec::push_all(p(cstore).used_link_args, str::split_char(args, ' '));
}
fn get_used_link_args(cstore: cstore) -> ~[~str] {
return p(cstore).used_link_args;
}
fn add_use_stmt_cnum(cstore: cstore, use_id: ast::node_id,
cnum: ast::crate_num) {
p(cstore).use_crate_map.insert(use_id, cnum);
}
fn find_use_stmt_cnum(cstore: cstore,
use_id: ast::node_id) -> Option<ast::crate_num> {
p(cstore).use_crate_map.find(use_id)
}
// returns hashes of crates directly used by this crate. Hashes are
// sorted by crate name.
fn get_dep_hashes(cstore: cstore) -> ~[~str] {
type crate_hash = {name: ~str, hash: ~str};
let mut result = ~[];
for p(cstore).use_crate_map.each_value |cnum| {
let cdata = cstore::get_crate_data(cstore, cnum);
let hash = decoder::get_crate_hash(cdata.data);
debug!("Add hash[%s]: %s", cdata.name, hash);
vec::push(result, {name: cdata.name, hash: hash});
};
pure fn lteq(a: &crate_hash, b: &crate_hash) -> bool {a.name <= b.name}
let sorted = std::sort::merge_sort(lteq, result);
debug!("sorted:");
for sorted.each |x| {
debug!(" hash[%s]: %s", x.name, x.hash);
}
fn mapper(ch: &crate_hash) -> ~str { return ch.hash; }
return vec::map(sorted, mapper);
}
fn get_path(cstore: cstore, d: ast::def_id) -> ~[~str] {
option::map_default(&p(cstore).mod_path_map.find(d), ~[],
|ds| str::split_str(*ds, ~"::"))
}
// Local Variables:
// mode: rust
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// End: