Skip to content

Commit 4165d36

Browse files
committed
Add a pass to fold out items that do not belong in the current configuration
The parser needs to parse unconfigured items into the AST so that they can make the round trip back through the pretty printer, but subsequent passes shouldn't care about items not being translated. Running a fold pass after parsing is the lowest-impact way to make this work. The performance seems fine. Issue #489
1 parent 3483c65 commit 4165d36

File tree

3 files changed

+71
-0
lines changed

3 files changed

+71
-0
lines changed

src/comp/driver/rustc.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,8 @@ fn compile_input(session::session sess, eval::env env, str input,
8080
auto crate =
8181
time(time_passes, "parsing", bind parse_input(sess, p, input));
8282
if (sess.get_opts().output_type == link::output_type_none) { ret; }
83+
crate = time(time_passes, "configuration",
84+
bind front::config::strip_unconfigured_items(crate));
8385
auto ast_map = time(time_passes, "ast indexing",
8486
bind middle::ast_map::map_crate(*crate));
8587
auto d =

src/comp/front/config.rs

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
import std::option;
2+
import std::vec;
3+
import ast;
4+
import fold;
5+
import attr;
6+
7+
export strip_unconfigured_items;
8+
9+
// Support conditional compilation by transforming the AST, stripping out
10+
// any items that do not belong in the current configuration
11+
fn strip_unconfigured_items(@ast::crate crate) -> @ast::crate {
12+
auto cfg = crate.node.config;
13+
14+
auto precursor = rec(fold_mod = bind fold_mod(cfg, _, _)
15+
with *fold::default_ast_fold());
16+
17+
auto fold = fold::make_fold(precursor);
18+
auto res = @fold.fold_crate(*crate);
19+
// FIXME: This is necessary to break a circular reference
20+
fold::dummy_out(fold);
21+
ret res;
22+
}
23+
24+
fn filter_item(&ast::crate_cfg cfg,
25+
&@ast::item item) -> option::t[@ast::item] {
26+
if (in_cfg(cfg, item)) {
27+
option::some(item)
28+
} else {
29+
option::none
30+
}
31+
}
32+
33+
fn fold_mod(&ast::crate_cfg cfg, &ast::_mod m,
34+
fold::ast_fold fld) -> ast::_mod {
35+
auto filter = bind filter_item(cfg, _);
36+
auto filtered_items = vec::filter_map(filter, m.items);
37+
ret rec(view_items=vec::map(fld.fold_view_item, m.view_items),
38+
items=vec::map(fld.fold_item, filtered_items));
39+
}
40+
41+
// Determine if an item should be translated in the current crate
42+
// configuration based on the item's attributes
43+
fn in_cfg(&ast::crate_cfg cfg, &@ast::item item) -> bool {
44+
45+
auto item_cfg_attrs = attr::find_attrs_by_name(item.attrs, "cfg");
46+
47+
auto item_has_cfg_attrs = vec::len(item_cfg_attrs) > 0u;
48+
if (!item_has_cfg_attrs) { ret true; }
49+
50+
auto item_cfg_metas = attr::attr_metas(item_cfg_attrs);
51+
52+
for (@ast::meta_item cfg_mi in item_cfg_metas) {
53+
if (attr::contains(cfg, cfg_mi)) {
54+
ret true;
55+
}
56+
}
57+
58+
ret false;
59+
}
60+
61+
62+
// Local Variables:
63+
// fill-column: 78;
64+
// indent-tabs-mode: nil
65+
// c-basic-offset: 4
66+
// buffer-file-coding-system: utf-8-unix
67+
// compile-command: "make -k -C $RBUILD 2>&1 | sed -e 's/\\/x\\//x:\\//g'";
68+
// End:

src/comp/rustc.rc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ mod front {
5757
mod parser;
5858
mod token;
5959
mod eval;
60+
mod config;
6061
}
6162

6263
mod back {

0 commit comments

Comments
 (0)