From 4165d3640a7b56f0d057a3d55992eb8c9ac05432 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Wed, 29 Jun 2011 22:32:08 -0700 Subject: [PATCH] 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 --- src/comp/driver/rustc.rs | 2 ++ src/comp/front/config.rs | 68 ++++++++++++++++++++++++++++++++++++++++ src/comp/rustc.rc | 1 + 3 files changed, 71 insertions(+) create mode 100644 src/comp/front/config.rs diff --git a/src/comp/driver/rustc.rs b/src/comp/driver/rustc.rs index d83e04e061ae..55dcc35a637a 100644 --- a/src/comp/driver/rustc.rs +++ b/src/comp/driver/rustc.rs @@ -80,6 +80,8 @@ fn compile_input(session::session sess, eval::env env, str input, auto crate = time(time_passes, "parsing", bind parse_input(sess, p, input)); if (sess.get_opts().output_type == link::output_type_none) { ret; } + crate = time(time_passes, "configuration", + bind front::config::strip_unconfigured_items(crate)); auto ast_map = time(time_passes, "ast indexing", bind middle::ast_map::map_crate(*crate)); auto d = diff --git a/src/comp/front/config.rs b/src/comp/front/config.rs new file mode 100644 index 000000000000..04429481b5a1 --- /dev/null +++ b/src/comp/front/config.rs @@ -0,0 +1,68 @@ +import std::option; +import std::vec; +import ast; +import fold; +import attr; + +export strip_unconfigured_items; + +// Support conditional compilation by transforming the AST, stripping out +// any items that do not belong in the current configuration +fn strip_unconfigured_items(@ast::crate crate) -> @ast::crate { + auto cfg = crate.node.config; + + auto precursor = rec(fold_mod = bind fold_mod(cfg, _, _) + with *fold::default_ast_fold()); + + auto fold = fold::make_fold(precursor); + auto res = @fold.fold_crate(*crate); + // FIXME: This is necessary to break a circular reference + fold::dummy_out(fold); + ret res; +} + +fn filter_item(&ast::crate_cfg cfg, + &@ast::item item) -> option::t[@ast::item] { + if (in_cfg(cfg, item)) { + option::some(item) + } else { + option::none + } +} + +fn fold_mod(&ast::crate_cfg cfg, &ast::_mod m, + fold::ast_fold fld) -> ast::_mod { + auto filter = bind filter_item(cfg, _); + auto filtered_items = vec::filter_map(filter, m.items); + ret rec(view_items=vec::map(fld.fold_view_item, m.view_items), + items=vec::map(fld.fold_item, filtered_items)); +} + +// Determine if an item should be translated in the current crate +// configuration based on the item's attributes +fn in_cfg(&ast::crate_cfg cfg, &@ast::item item) -> bool { + + auto item_cfg_attrs = attr::find_attrs_by_name(item.attrs, "cfg"); + + auto item_has_cfg_attrs = vec::len(item_cfg_attrs) > 0u; + if (!item_has_cfg_attrs) { ret true; } + + auto item_cfg_metas = attr::attr_metas(item_cfg_attrs); + + for (@ast::meta_item cfg_mi in item_cfg_metas) { + if (attr::contains(cfg, cfg_mi)) { + ret true; + } + } + + ret false; +} + + +// Local Variables: +// fill-column: 78; +// indent-tabs-mode: nil +// c-basic-offset: 4 +// buffer-file-coding-system: utf-8-unix +// compile-command: "make -k -C $RBUILD 2>&1 | sed -e 's/\\/x\\//x:\\//g'"; +// End: diff --git a/src/comp/rustc.rc b/src/comp/rustc.rc index 6b87ce624fa7..0fb9f2332559 100644 --- a/src/comp/rustc.rc +++ b/src/comp/rustc.rc @@ -57,6 +57,7 @@ mod front { mod parser; mod token; mod eval; + mod config; } mod back {