]> git.lizzy.rs Git - rust.git/blob - src/librustc/front/config.rs
Remove 'Local Variable' comments
[rust.git] / src / librustc / front / config.rs
1 // Copyright 2012 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
4 //
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10
11 use syntax::{ast, fold, attr};
12
13 type in_cfg_pred = @fn(attrs: ~[ast::attribute]) -> bool;
14
15 struct Context {
16     in_cfg: in_cfg_pred
17 }
18
19 // Support conditional compilation by transforming the AST, stripping out
20 // any items that do not belong in the current configuration
21 pub fn strip_unconfigured_items(crate: @ast::crate) -> @ast::crate {
22     do strip_items(crate) |attrs| {
23         in_cfg(/*bad*/copy crate.node.config, attrs)
24     }
25 }
26
27 pub fn strip_items(crate: @ast::crate, in_cfg: in_cfg_pred)
28     -> @ast::crate {
29
30     let ctxt = @Context { in_cfg: in_cfg };
31
32     let precursor = @fold::AstFoldFns {
33           fold_mod: |a,b| fold_mod(ctxt, a, b),
34           fold_block: fold::wrap(|a,b| fold_block(ctxt, a, b) ),
35           fold_foreign_mod: |a,b| fold_foreign_mod(ctxt, a, b),
36           fold_item_underscore: |a,b| {
37             // Bad copy.
38             fold_item_underscore(ctxt, copy a, b)
39           },
40           .. *fold::default_ast_fold()};
41
42     let fold = fold::make_fold(precursor);
43     let res = @fold.fold_crate(&*crate);
44     return res;
45 }
46
47 fn filter_item(cx: @Context, item: @ast::item) ->
48    Option<@ast::item> {
49     if item_in_cfg(cx, item) { option::Some(item) } else { option::None }
50 }
51
52 fn filter_view_item(cx: @Context, view_item: @ast::view_item
53                    )-> Option<@ast::view_item> {
54     if view_item_in_cfg(cx, view_item) {
55         option::Some(view_item)
56     } else {
57         option::None
58     }
59 }
60
61 fn fold_mod(cx: @Context, m: &ast::_mod, fld: @fold::ast_fold) -> ast::_mod {
62     let filtered_items =
63         m.items.filter_mapped(|a| filter_item(cx, *a));
64     let filtered_view_items =
65         m.view_items.filter_mapped(|a| filter_view_item(cx, *a));
66     ast::_mod {
67         view_items: filtered_view_items.map(|x| fld.fold_view_item(*x)),
68         items: vec::filter_map(filtered_items, |x| fld.fold_item(x))
69     }
70 }
71
72 fn filter_foreign_item(cx: @Context, item: @ast::foreign_item) ->
73    Option<@ast::foreign_item> {
74     if foreign_item_in_cfg(cx, item) {
75         option::Some(item)
76     } else { option::None }
77 }
78
79 fn fold_foreign_mod(
80     cx: @Context,
81     nm: &ast::foreign_mod,
82     fld: @fold::ast_fold
83 ) -> ast::foreign_mod {
84     let filtered_items =
85         nm.items.filter_mapped(|a| filter_foreign_item(cx, *a));
86     let filtered_view_items =
87         nm.view_items.filter_mapped(|a| filter_view_item(cx, *a));
88     ast::foreign_mod {
89         sort: nm.sort,
90         abis: nm.abis,
91         view_items: vec::map(filtered_view_items, |x| fld.fold_view_item(*x)),
92         items: filtered_items
93     }
94 }
95
96 fn fold_item_underscore(cx: @Context, item: &ast::item_,
97                         fld: @fold::ast_fold) -> ast::item_ {
98     let item = match *item {
99         ast::item_impl(ref a, b, c, ref methods) => {
100             let methods = methods.filtered(|m| method_in_cfg(cx, *m) );
101             ast::item_impl(/*bad*/ copy *a, b, c, methods)
102         }
103         ast::item_trait(ref a, ref b, ref methods) => {
104             let methods = methods.filtered(|m| trait_method_in_cfg(cx, m) );
105             ast::item_trait(/*bad*/copy *a, /*bad*/copy *b, methods)
106         }
107         ref item => /*bad*/ copy *item
108     };
109
110     fold::noop_fold_item_underscore(&item, fld)
111 }
112
113 fn filter_stmt(cx: @Context, stmt: @ast::stmt) ->
114    Option<@ast::stmt> {
115     match stmt.node {
116       ast::stmt_decl(decl, _) => {
117         match decl.node {
118           ast::decl_item(item) => {
119             if item_in_cfg(cx, item) {
120                 option::Some(stmt)
121             } else { option::None }
122           }
123           _ => option::Some(stmt)
124         }
125       }
126       _ => option::Some(stmt)
127     }
128 }
129
130 fn fold_block(
131     cx: @Context,
132     b: &ast::blk_,
133     fld: @fold::ast_fold
134 ) -> ast::blk_ {
135     let filtered_stmts =
136         b.stmts.filter_mapped(|a| filter_stmt(cx, *a));
137     ast::blk_ {
138         view_items: /*bad*/copy b.view_items,
139         stmts: vec::map(filtered_stmts, |x| fld.fold_stmt(*x)),
140         expr: b.expr.map(|x| fld.fold_expr(*x)),
141         id: b.id,
142         rules: b.rules,
143     }
144 }
145
146 fn item_in_cfg(cx: @Context, item: @ast::item) -> bool {
147     return (cx.in_cfg)(/*bad*/copy item.attrs);
148 }
149
150 fn foreign_item_in_cfg(cx: @Context, item: @ast::foreign_item) -> bool {
151     return (cx.in_cfg)(/*bad*/copy item.attrs);
152 }
153
154 fn view_item_in_cfg(cx: @Context, item: @ast::view_item) -> bool {
155     return (cx.in_cfg)(/*bad*/copy item.attrs);
156 }
157
158 fn method_in_cfg(cx: @Context, meth: @ast::method) -> bool {
159     return (cx.in_cfg)(/*bad*/copy meth.attrs);
160 }
161
162 fn trait_method_in_cfg(cx: @Context, meth: &ast::trait_method) -> bool {
163     match *meth {
164         ast::required(ref meth) => (cx.in_cfg)(/*bad*/copy meth.attrs),
165         ast::provided(@ref meth) => (cx.in_cfg)(/*bad*/copy meth.attrs)
166     }
167 }
168
169 // Determine if an item should be translated in the current crate
170 // configuration based on the item's attributes
171 fn in_cfg(cfg: ast::crate_cfg, attrs: ~[ast::attribute]) -> bool {
172     metas_in_cfg(cfg, attr::attr_metas(attrs))
173 }
174
175 pub fn metas_in_cfg(cfg: ast::crate_cfg,
176                     metas: ~[@ast::meta_item]) -> bool {
177     // The "cfg" attributes on the item
178     let cfg_metas = attr::find_meta_items_by_name(metas, ~"cfg");
179
180     // Pull the inner meta_items from the #[cfg(meta_item, ...)]  attributes,
181     // so we can match against them. This is the list of configurations for
182     // which the item is valid
183     let cfg_metas = vec::filter_map(cfg_metas, |i| attr::get_meta_item_list(i));
184
185     if cfg_metas.all(|c| c.is_empty()) { return true; }
186
187     cfg_metas.any(|cfg_meta| {
188         cfg_meta.all(|cfg_mi| {
189             match cfg_mi.node {
190                 ast::meta_list(s, ref it) if *s == ~"not"
191                     => it.all(|mi| !attr::contains(cfg, *mi)),
192                 _ => attr::contains(cfg, *cfg_mi)
193             }
194         })
195     })
196 }