// mod bar { macro_rules! baz!(() => {{}}) }
//
// baz! should not use this definition unless foo is enabled.
+ crate = time(time_passes, ~"std macros injection", ||
+ syntax::ext::expand::inject_std_macros(sess.parse_sess, copy cfg,
+ crate));
+
crate = time(time_passes, ~"configuration 1", ||
front::config::strip_unconfigured_items(crate));
assert!(phases.from != cu_no_trans);
let (llcx, llmod, link_meta) = {
- crate = time(time_passes, ~"extra injection", ||
+ crate = time(time_passes, ~"std injection", ||
front::std_inject::maybe_inject_libstd_ref(sess, crate));
let ast_map = time(time_passes, ~"ast indexing", ||
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use ast::{blk_, attribute_, attr_outer, meta_word};
-use ast::{crate, expr_, expr_mac, mac_invoc_tt};
+use ast::{blk_, crate, expr_, expr_mac, mac_invoc_tt};
use ast::{item_mac, stmt_, stmt_mac, stmt_expr, stmt_semi};
use ast::{illegal_ctxt};
use ast;
use ast_util::{new_rename, new_mark, resolve};
use attr;
use codemap;
-use codemap::{span, ExpnInfo, NameAndSpan, spanned};
+use codemap::{span, ExpnInfo, NameAndSpan};
use ext::base::*;
use fold::*;
use parse;
// the default compilation environment. It would be much nicer to use
// a mechanism like syntax_quote to ensure hygiene.
-pub fn core_macros() -> @str {
+pub fn std_macros() -> @str {
return
-@"pub mod macros {
+@"pub mod __std_macros {
+ #[macro_escape];
+
macro_rules! ignore (($($x:tt)*) => (()))
macro_rules! error (
)
)
- macro_rules! debug (
+ // conditionally define debug!, but keep it type checking even
+ // in non-debug builds.
+ macro_rules! __debug (
($arg:expr) => (
__log(4u32, fmt!( \"%?\", $arg ))
);
)
)
+ #[cfg(debug)]
+ #[macro_escape]
+ mod debug_macro {
+ macro_rules! debug (($($arg:expr),*) => {
+ __debug!($($arg),*)
+ })
+ }
+
+ #[cfg(not(debug))]
+ #[macro_escape]
+ mod debug_macro {
+ macro_rules! debug (($($arg:expr),*) => {
+ if false { __debug!($($arg),*) }
+ })
+ }
+
macro_rules! fail(
() => (
fail!(\"explicit failure\")
}";
}
+// add a bunch of macros as though they were placed at the head of the
+// program (ick). This should run before cfg stripping.
+pub fn inject_std_macros(parse_sess: @mut parse::ParseSess,
+ cfg: ast::crate_cfg, c: &crate) -> @crate {
+ let sm = match parse_item_from_source_str(@"<std-macros>",
+ std_macros(),
+ copy cfg,
+ ~[],
+ parse_sess) {
+ Some(item) => item,
+ None => fail!("expected core macros to parse correctly")
+ };
+
+ let injecter = @AstFoldFns {
+ fold_mod: |modd, _| {
+ // just inject the std macros at the start of the first
+ // module in the crate (i.e the crate file itself.)
+ let items = vec::append(~[sm], modd.items);
+ ast::_mod {
+ items: items,
+ // FIXME #2543: Bad copy.
+ .. copy *modd
+ }
+ },
+ .. *default_ast_fold()
+ };
+ @make_fold(injecter).fold_crate(c)
+}
+
pub fn expand_crate(parse_sess: @mut parse::ParseSess,
cfg: ast::crate_cfg, c: &crate) -> @crate {
// adding *another* layer of indirection here so that the block
new_span: |a| new_span(cx, a),
.. *afp};
let f = make_fold(f_pre);
- // add a bunch of macros as though they were placed at the
- // head of the program (ick).
- let attrs = ~[
- spanned {
- span: codemap::dummy_sp(),
- node: attribute_ {
- style: attr_outer,
- value: @spanned {
- node: meta_word(@"macro_escape"),
- span: codemap::dummy_sp(),
- },
- is_sugared_doc: false,
- }
- }
- ];
-
- let cm = match parse_item_from_source_str(@"<core-macros>",
- core_macros(),
- copy cfg,
- attrs,
- parse_sess) {
- Some(item) => item,
- None => cx.bug("expected core macros to parse correctly")
- };
- // This is run for its side-effects on the expander env,
- // as it registers all the core macros as expanders.
- f.fold_item(cm);
@f.fold_crate(c)
}
@"<test>",
src,
~[],sess);
+ let crate_ast = inject_std_macros(sess, ~[], crate_ast);
+ // don't bother with striping, doesn't affect fail!.
expand_crate(sess,~[],crate_ast);
}
expand_crate(sess,~[],crate_ast);
}
- #[test] fn core_macros_must_parse () {
- let src = @"
- pub mod macros {
- macro_rules! ignore (($($x:tt)*) => (()))
-
- macro_rules! error ( ($( $arg:expr ),+) => (
- log(::core::error, fmt!( $($arg),+ )) ))
-}";
+ #[test] fn std_macros_must_parse () {
+ let src = super::std_macros();
let sess = parse::new_parse_sess(None);
let cfg = ~[];
let item_ast = parse::parse_item_from_source_str(
@"<test>",
src,
- cfg,~[make_dummy_attr (@"macro_escape")],sess);
+ cfg,~[],sess);
match item_ast {
Some(_) => (), // success
None => fail!("expected this to parse")
--- /dev/null
+// Copyright 2012 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// xfail-fast compile-flags directive doesn't work for check-fast
+// compile-flags: --cfg debug
+// exec-env:RUST_LOG=conditional-debug-macro-on=4
+
+fn main() {
+ // exits early if debug! evaluates its arguments, otherwise it
+ // will hit the fail.
+ debug!({ if true { return; } });
+
+ fail!();
+}
\ No newline at end of file