From e995d9935b5bccb484db85b75a344258e74f21a5 Mon Sep 17 00:00:00 2001 From: Huon Wilson Date: Thu, 1 Aug 2013 23:03:03 +1000 Subject: [PATCH] syntax: implement cfg!() which evaluates to true/false where #[cfg] would keep/remove. Example: if cfg!(test) { calculation_to_run_only_when_testing(); } --- src/libsyntax/ext/base.rs | 2 + src/libsyntax/ext/cfg.rs | 45 +++++++++++++++++++++++ src/libsyntax/syntax.rs | 1 + src/test/run-pass/syntax-extension-cfg.rs | 35 ++++++++++++++++++ 4 files changed, 83 insertions(+) create mode 100644 src/libsyntax/ext/cfg.rs create mode 100644 src/test/run-pass/syntax-extension-cfg.rs diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index ea87646e60b0b..64130b0f83337 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -201,6 +201,8 @@ pub fn syntax_expander_table() -> SyntaxEnv { builtin_item_tt(ext::pipes::expand_proto)); syntax_expanders.insert(intern(&"asm"), builtin_normal_tt(ext::asm::expand_asm)); + syntax_expanders.insert(intern(&"cfg"), + builtin_normal_tt(ext::cfg::expand_cfg)); syntax_expanders.insert( intern(&"trace_macros"), builtin_normal_tt(ext::trace_macros::expand_trace_macros)); diff --git a/src/libsyntax/ext/cfg.rs b/src/libsyntax/ext/cfg.rs new file mode 100644 index 0000000000000..069cac0103677 --- /dev/null +++ b/src/libsyntax/ext/cfg.rs @@ -0,0 +1,45 @@ +// Copyright 2013 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +/** +The compiler code necessary to support the cfg! extension, which +expands to a literal `true` or `false` based on whether the given cfgs +match the current compilation environment. +*/ + +use ast; +use codemap::span; +use ext::base::*; +use ext::base; +use ext::build::AstBuilder; +use attr; +use attr::*; +use parse; +use parse::token; +use parse::attr::parser_attr; + +pub fn expand_cfg(cx: @ExtCtxt, sp: span, tts: &[ast::token_tree]) -> base::MacResult { + let p = parse::new_parser_from_tts(cx.parse_sess(), cx.cfg(), tts.to_owned()); + + let mut cfgs = ~[]; + // parse `cfg!(meta_item, meta_item(x,y), meta_item="foo", ...)` + while *p.token != token::EOF { + cfgs.push(p.parse_meta_item()); + if p.eat(&token::EOF) { break } // trailing comma is optional,. + p.expect(&token::COMMA); + } + + // test_cfg searches for meta items looking like `cfg(foo, ...)` + let in_cfg = &[cx.meta_list(sp, @"cfg", cfgs)]; + + let matches_cfg = attr::test_cfg(cx.cfg(), in_cfg.iter().transform(|&x| x)); + let e = cx.expr_bool(sp, matches_cfg); + MRExpr(e) +} diff --git a/src/libsyntax/syntax.rs b/src/libsyntax/syntax.rs index ae2aa6ae73891..8005704ee3363 100644 --- a/src/libsyntax/syntax.rs +++ b/src/libsyntax/syntax.rs @@ -70,6 +70,7 @@ pub mod ext { } + pub mod cfg; pub mod fmt; pub mod env; pub mod bytes; diff --git a/src/test/run-pass/syntax-extension-cfg.rs b/src/test/run-pass/syntax-extension-cfg.rs new file mode 100644 index 0000000000000..321929207f7a6 --- /dev/null +++ b/src/test/run-pass/syntax-extension-cfg.rs @@ -0,0 +1,35 @@ +// Copyright 2013 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// xfail-fast compile-flags doesn't work with fast-check +// compile-flags: --cfg foo --cfg bar(baz) --cfg qux="foo" + +fn main() { + // check + if ! cfg!(foo) { fail!() } + if cfg!(not(foo)) { fail!() } + + if ! cfg!(bar(baz)) { fail!() } + if cfg!(not(bar(baz))) { fail!() } + + if ! cfg!(qux="foo") { fail!() } + if cfg!(not(qux="foo")) { fail!() } + + if ! cfg!(foo, bar(baz), qux="foo") { fail!() } + if cfg!(not(foo, bar(baz), qux="foo")) { fail!() } + + if cfg!(not_a_cfg) { fail!() } + if cfg!(not_a_cfg, foo, bar(baz), qux="foo") { fail!() } + + if ! cfg!(not(not_a_cfg)) { fail!() } + if ! cfg!(not(not_a_cfg), foo, bar(baz), qux="foo") { fail!() } + + if cfg!(trailing_comma, ) { fail!() } +}