about summary refs log tree commit diff
diff options
context:
space:
mode:
authorHuon Wilson <dbau.pp+github@gmail.com>2014-03-18 23:14:08 +1100
committerHuon Wilson <dbau.pp+github@gmail.com>2014-03-22 01:27:23 +1100
commitcda33346d0e9e4d1ff26163583831f96d42a4bc0 (patch)
tree4ed80fc23ba6ee22c9c9be1c9fe3d093a7110a35
parentaf9368452d8578af219713b34f7e3be4bd085186 (diff)
downloadrust-cda33346d0e9e4d1ff26163583831f96d42a4bc0.tar.gz
rust-cda33346d0e9e4d1ff26163583831f96d42a4bc0.zip
syntax: allow `trace_macros!` and `log_syntax!` in item position.
Previously

    trace_macros!(true)
    fn main() {}

would complain about `trace_macros` being an expression macro in item
position. This is a pointless limitation, because the macro is purely
compile-time, with no runtime effect. (And similarly for log_syntax.)

This also changes the behaviour of `trace_macros!` very slightly, it
used to be equivalent to

    macro_rules! trace_macros {
        (true $($_x: tt)*) => { true };
        (false $($_x: tt)*) => { false }
    }

I.e. you could invoke it with arbitrary trailing arguments, which were
ignored. It is changed to accept only exactly `true` or `false` (with no
trailing arguments) and expands to `()`.
-rw-r--r--src/libsyntax/ext/base.rs22
-rw-r--r--src/libsyntax/ext/log_syntax.rs14
-rw-r--r--src/libsyntax/ext/trace_macros.rs32
-rw-r--r--src/test/compile-fail/issue-11692.rs1
-rw-r--r--src/test/compile-fail/trace_macros-format.rs29
-rw-r--r--src/test/run-pass/log_syntax-trace_macros-macro-locations.rs30
6 files changed, 92 insertions, 36 deletions
diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs
index df2c265e6eb..97f85a1c807 100644
--- a/src/libsyntax/ext/base.rs
+++ b/src/libsyntax/ext/base.rs
@@ -120,13 +120,31 @@ impl MacResult {
     pub fn raw_dummy_expr(sp: codemap::Span) -> @ast::Expr {
         @ast::Expr {
             id: ast::DUMMY_NODE_ID,
-            node: ast::ExprTup(Vec::new()),
-            span: sp
+            node: ast::ExprLit(@codemap::respan(sp, ast::LitNil)),
+            span: sp,
         }
     }
     pub fn dummy_expr(sp: codemap::Span) -> MacResult {
         MRExpr(MacResult::raw_dummy_expr(sp))
     }
+    pub fn dummy_any(sp: codemap::Span) -> MacResult {
+        MRAny(~DummyMacResult { sp: sp })
+    }
+}
+struct DummyMacResult {
+    sp: codemap::Span
+}
+impl AnyMacro for DummyMacResult {
+    fn make_expr(&self) -> @ast::Expr {
+        MacResult::raw_dummy_expr(self.sp)
+    }
+    fn make_items(&self) -> SmallVector<@ast::Item> {
+        SmallVector::zero()
+    }
+    fn make_stmt(&self) -> @ast::Stmt {
+        @codemap::respan(self.sp,
+                         ast::StmtExpr(MacResult::raw_dummy_expr(self.sp), ast::DUMMY_NODE_ID))
+    }
 }
 
 /// An enum representing the different kinds of syntax extensions.
diff --git a/src/libsyntax/ext/log_syntax.rs b/src/libsyntax/ext/log_syntax.rs
index b94928238e9..1ce08b8303e 100644
--- a/src/libsyntax/ext/log_syntax.rs
+++ b/src/libsyntax/ext/log_syntax.rs
@@ -10,11 +10,10 @@
 
 use ast;
 use codemap;
-use ext::base::*;
 use ext::base;
 use print;
 
-pub fn expand_syntax_ext(cx: &mut ExtCtxt,
+pub fn expand_syntax_ext(cx: &mut base::ExtCtxt,
                          sp: codemap::Span,
                          tt: &[ast::TokenTree])
                       -> base::MacResult {
@@ -23,13 +22,6 @@ pub fn expand_syntax_ext(cx: &mut ExtCtxt,
     println!("{}", print::pprust::tt_to_str(&ast::TTDelim(
                 @tt.iter().map(|x| (*x).clone()).collect())));
 
-    //trivial expression
-    MRExpr(@ast::Expr {
-        id: ast::DUMMY_NODE_ID,
-        node: ast::ExprLit(@codemap::Spanned {
-            node: ast::LitNil,
-            span: sp
-        }),
-        span: sp,
-    })
+    // any so that `log_syntax` can be invoked as an expression and item.
+    base::MacResult::dummy_any(sp)
 }
diff --git a/src/libsyntax/ext/trace_macros.rs b/src/libsyntax/ext/trace_macros.rs
index fa49f06e516..173cf4c9ad9 100644
--- a/src/libsyntax/ext/trace_macros.rs
+++ b/src/libsyntax/ext/trace_macros.rs
@@ -12,33 +12,21 @@ use ast;
 use codemap::Span;
 use ext::base::ExtCtxt;
 use ext::base;
-use parse::lexer::{new_tt_reader, Reader};
-use parse::parser::Parser;
-use parse::token::keywords;
+use parse::token::{keywords, is_keyword};
 
 pub fn expand_trace_macros(cx: &mut ExtCtxt,
                            sp: Span,
                            tt: &[ast::TokenTree])
                         -> base::MacResult {
-    let sess = cx.parse_sess();
-    let cfg = cx.cfg();
-    let tt_rdr = new_tt_reader(&cx.parse_sess().span_diagnostic,
-                               None,
-                               tt.iter().map(|x| (*x).clone()).collect());
-    let mut rust_parser = Parser(sess, cfg.clone(), tt_rdr.dup());
-
-    if rust_parser.is_keyword(keywords::True) {
-        cx.set_trace_macros(true);
-    } else if rust_parser.is_keyword(keywords::False) {
-        cx.set_trace_macros(false);
-    } else {
-        cx.span_err(sp, "trace_macros! only accepts `true` or `false`");
-        return base::MacResult::dummy_expr(sp);
+    match tt {
+        [ast::TTTok(_, ref tok)] if is_keyword(keywords::True, tok) => {
+            cx.set_trace_macros(true);
+        }
+        [ast::TTTok(_, ref tok)] if is_keyword(keywords::False, tok) => {
+            cx.set_trace_macros(false);
+        }
+        _ => cx.span_err(sp, "trace_macros! accepts only `true` or `false`"),
     }
 
-    rust_parser.bump();
-
-    let mut rust_parser = Parser(sess, cfg, tt_rdr.dup());
-    let result = rust_parser.parse_expr();
-    base::MRExpr(result)
+    base::MacResult::dummy_any(sp)
 }
diff --git a/src/test/compile-fail/issue-11692.rs b/src/test/compile-fail/issue-11692.rs
index aed2c4d579a..848deac4d55 100644
--- a/src/test/compile-fail/issue-11692.rs
+++ b/src/test/compile-fail/issue-11692.rs
@@ -15,5 +15,4 @@ fn main() {
 
     concat!(test!());
     //~^ ERROR: macro undefined: 'test'
-    //~^^ ERROR: expected a literal
 }
diff --git a/src/test/compile-fail/trace_macros-format.rs b/src/test/compile-fail/trace_macros-format.rs
new file mode 100644
index 00000000000..557dcdc73c8
--- /dev/null
+++ b/src/test/compile-fail/trace_macros-format.rs
@@ -0,0 +1,29 @@
+// Copyright 2014 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.
+
+// ignore-fast feature doesn't work
+#[feature(macro_rules, trace_macros)];
+
+fn main() {
+    trace_macros!(); //~ ERROR trace_macros! accepts only `true` or `false`
+    trace_macros!(1); //~ ERROR trace_macros! accepts only `true` or `false`
+    trace_macros!(ident); //~ ERROR trace_macros! accepts only `true` or `false`
+    trace_macros!(for); //~ ERROR trace_macros! accepts only `true` or `false`
+    trace_macros!(true,); //~ ERROR trace_macros! accepts only `true` or `false`
+    trace_macros!(false 1); //~ ERROR trace_macros! accepts only `true` or `false`
+
+
+    // should be fine:
+    macro_rules! expando {
+        ($x: ident) => { trace_macros!($x) }
+    }
+
+    expando!(true);
+}
diff --git a/src/test/run-pass/log_syntax-trace_macros-macro-locations.rs b/src/test/run-pass/log_syntax-trace_macros-macro-locations.rs
new file mode 100644
index 00000000000..a00ba6067dc
--- /dev/null
+++ b/src/test/run-pass/log_syntax-trace_macros-macro-locations.rs
@@ -0,0 +1,30 @@
+// Copyright 2014 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.
+
+// ignore-fast feature doesn't work
+#[feature(trace_macros, log_syntax)];
+
+// make sure these macros can be used as in the various places that
+// macros can occur.
+
+// items
+trace_macros!(false)
+log_syntax!()
+
+fn main() {
+
+    // statements
+    trace_macros!(false);
+    log_syntax!();
+
+    // expressions
+    (trace_macros!(false),
+     log_syntax!());
+}