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
|
use parser::Parser;
use attr::parser_attr;
use ast_util::mk_sp;
use codemap::span;
export eval_crate_directives_to_mod;
export eval_src_mod;
export eval_src_mod_from_path;
type ctx =
@{sess: parse::parse_sess,
cfg: ast::crate_cfg};
fn eval_crate_directives(cx: ctx,
cdirs: ~[@ast::crate_directive],
prefix: &Path,
view_items: &mut~[@ast::view_item],
items: &mut~[@ast::item]) {
for cdirs.each |sub_cdir| {
eval_crate_directive(cx, *sub_cdir, prefix, view_items, items);
}
}
fn eval_crate_directives_to_mod(cx: ctx, cdirs: ~[@ast::crate_directive],
prefix: &Path, suffix: &Option<Path>)
-> (ast::_mod, ~[ast::attribute]) {
let (cview_items, citems, cattrs)
= parse_companion_mod(cx, prefix, suffix);
let mut view_items: ~[@ast::view_item] = ~[];
let mut items: ~[@ast::item] = ~[];
eval_crate_directives(cx, cdirs, prefix, &mut view_items, &mut items);
return ({view_items: vec::append(view_items, cview_items),
items: vec::append(items, citems)},
cattrs);
}
/*
The 'companion mod'. So .rc crates and directory mod crate directives define
modules but not a .rs file to fill those mods with stuff. The companion mod is
a convention for location a .rs file to go with them. For .rc files the
companion mod is a .rs file with the same name; for directory mods the
companion mod is a .rs file with the same name as the directory.
We build the path to the companion mod by combining the prefix and the
optional suffix then adding the .rs extension.
*/
fn parse_companion_mod(cx: ctx, prefix: &Path, suffix: &Option<Path>)
-> (~[@ast::view_item], ~[@ast::item], ~[ast::attribute]) {
fn companion_file(prefix: &Path, suffix: &Option<Path>) -> Path {
return match *suffix {
option::Some(s) => prefix.push_many(s.components),
option::None => copy *prefix
}.with_filetype("rs");
}
fn file_exists(path: &Path) -> bool {
// Crude, but there's no lib function for this and I'm not
// up to writing it just now
match io::file_reader(path) {
result::Ok(_) => true,
result::Err(_) => false
}
}
let modpath = &companion_file(prefix, suffix);
if file_exists(modpath) {
debug!("found companion mod");
// XXX: Using a dummy span, but this code will go away soon
let p0 = new_sub_parser_from_file(cx.sess, cx.cfg,
modpath,
ast_util::dummy_sp());
let inner_attrs = p0.parse_inner_attrs_and_next();
let m0 = p0.parse_mod_items(token::EOF, inner_attrs.next);
return (m0.view_items, m0.items, inner_attrs.inner);
} else {
return (~[], ~[], ~[]);
}
}
fn cdir_path_opt(default: ~str, attrs: ~[ast::attribute]) -> ~str {
match ::attr::first_attr_value_str_by_name(attrs, ~"path") {
Some(d) => d,
None => default
}
}
fn eval_src_mod(cx: ctx, prefix: &Path,
outer_attrs: ~[ast::attribute],
id: ast::ident, sp: span
) -> (ast::item_, ~[ast::attribute]) {
let file_path = Path(cdir_path_opt(
cx.sess.interner.get(id) + ~".rs", outer_attrs));
eval_src_mod_from_path(cx, prefix, &file_path, outer_attrs, sp)
}
fn eval_src_mod_from_path(cx: ctx, prefix: &Path, path: &Path,
outer_attrs: ~[ast::attribute],
sp: span
) -> (ast::item_, ~[ast::attribute]) {
let full_path = if path.is_absolute {
copy *path
} else {
prefix.push_many(path.components)
};
let p0 =
new_sub_parser_from_file(cx.sess, cx.cfg,
&full_path, sp);
let inner_attrs = p0.parse_inner_attrs_and_next();
let mod_attrs = vec::append(outer_attrs, inner_attrs.inner);
let first_item_outer_attrs = inner_attrs.next;
let m0 = p0.parse_mod_items(token::EOF, first_item_outer_attrs);
return (ast::item_mod(m0), mod_attrs);
}
// XXX: Duplicated from parser.rs
fn mk_item(ctx: ctx, lo: BytePos, hi: BytePos, +ident: ast::ident,
+node: ast::item_, vis: ast::visibility,
+attrs: ~[ast::attribute]) -> @ast::item {
return @{ident: ident,
attrs: attrs,
id: next_node_id(ctx.sess),
node: node,
vis: vis,
span: mk_sp(lo, hi)};
}
fn eval_crate_directive(cx: ctx, cdir: @ast::crate_directive, prefix: &Path,
view_items: &mut ~[@ast::view_item],
items: &mut ~[@ast::item]) {
match cdir.node {
ast::cdir_src_mod(vis, id, attrs) => {
let (m, mod_attrs) = eval_src_mod(cx, prefix, attrs, id, cdir.span);
let i = mk_item(cx, cdir.span.lo, cdir.span.hi,
/* FIXME (#2543) */ copy id,
m, vis, mod_attrs);
items.push(i);
}
ast::cdir_dir_mod(vis, id, cdirs, attrs) => {
let path = Path(cdir_path_opt(*cx.sess.interner.get(id), attrs));
let full_path = if path.is_absolute {
copy path
} else {
prefix.push_many(path.components)
};
let (m0, a0) = eval_crate_directives_to_mod(
cx, cdirs, &full_path, &None);
let i =
@{ident: /* FIXME (#2543) */ copy id,
attrs: vec::append(attrs, a0),
id: cx.sess.next_id,
node: ast::item_mod(m0),
vis: vis,
span: cdir.span};
cx.sess.next_id += 1;
items.push(i);
}
ast::cdir_view_item(vi) => view_items.push(vi),
}
}
//
// Local Variables:
// mode: rust
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// End:
//
|