auto merge of #12998 : huonw/rust/log_syntax, r=alexcrichton
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 `()`.
This commit is contained in:
@@ -119,13 +119,31 @@ impl MacResult {
|
|||||||
pub fn raw_dummy_expr(sp: codemap::Span) -> @ast::Expr {
|
pub fn raw_dummy_expr(sp: codemap::Span) -> @ast::Expr {
|
||||||
@ast::Expr {
|
@ast::Expr {
|
||||||
id: ast::DUMMY_NODE_ID,
|
id: ast::DUMMY_NODE_ID,
|
||||||
node: ast::ExprTup(Vec::new()),
|
node: ast::ExprLit(@codemap::respan(sp, ast::LitNil)),
|
||||||
span: sp
|
span: sp,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn dummy_expr(sp: codemap::Span) -> MacResult {
|
pub fn dummy_expr(sp: codemap::Span) -> MacResult {
|
||||||
MRExpr(MacResult::raw_dummy_expr(sp))
|
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.
|
/// An enum representing the different kinds of syntax extensions.
|
||||||
|
|||||||
@@ -10,11 +10,10 @@
|
|||||||
|
|
||||||
use ast;
|
use ast;
|
||||||
use codemap;
|
use codemap;
|
||||||
use ext::base::*;
|
|
||||||
use ext::base;
|
use ext::base;
|
||||||
use print;
|
use print;
|
||||||
|
|
||||||
pub fn expand_syntax_ext(cx: &mut ExtCtxt,
|
pub fn expand_syntax_ext(cx: &mut base::ExtCtxt,
|
||||||
sp: codemap::Span,
|
sp: codemap::Span,
|
||||||
tt: &[ast::TokenTree])
|
tt: &[ast::TokenTree])
|
||||||
-> base::MacResult {
|
-> base::MacResult {
|
||||||
@@ -23,13 +22,6 @@ pub fn expand_syntax_ext(cx: &mut ExtCtxt,
|
|||||||
println!("{}", print::pprust::tt_to_str(&ast::TTDelim(
|
println!("{}", print::pprust::tt_to_str(&ast::TTDelim(
|
||||||
@tt.iter().map(|x| (*x).clone()).collect())));
|
@tt.iter().map(|x| (*x).clone()).collect())));
|
||||||
|
|
||||||
//trivial expression
|
// any so that `log_syntax` can be invoked as an expression and item.
|
||||||
MRExpr(@ast::Expr {
|
base::MacResult::dummy_any(sp)
|
||||||
id: ast::DUMMY_NODE_ID,
|
|
||||||
node: ast::ExprLit(@codemap::Spanned {
|
|
||||||
node: ast::LitNil,
|
|
||||||
span: sp
|
|
||||||
}),
|
|
||||||
span: sp,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,33 +12,21 @@ use ast;
|
|||||||
use codemap::Span;
|
use codemap::Span;
|
||||||
use ext::base::ExtCtxt;
|
use ext::base::ExtCtxt;
|
||||||
use ext::base;
|
use ext::base;
|
||||||
use parse::lexer::{new_tt_reader, Reader};
|
use parse::token::{keywords, is_keyword};
|
||||||
use parse::parser::Parser;
|
|
||||||
use parse::token::keywords;
|
|
||||||
|
|
||||||
pub fn expand_trace_macros(cx: &mut ExtCtxt,
|
pub fn expand_trace_macros(cx: &mut ExtCtxt,
|
||||||
sp: Span,
|
sp: Span,
|
||||||
tt: &[ast::TokenTree])
|
tt: &[ast::TokenTree])
|
||||||
-> base::MacResult {
|
-> base::MacResult {
|
||||||
let sess = cx.parse_sess();
|
match tt {
|
||||||
let cfg = cx.cfg();
|
[ast::TTTok(_, ref tok)] if is_keyword(keywords::True, tok) => {
|
||||||
let tt_rdr = new_tt_reader(&cx.parse_sess().span_diagnostic,
|
cx.set_trace_macros(true);
|
||||||
None,
|
}
|
||||||
tt.iter().map(|x| (*x).clone()).collect());
|
[ast::TTTok(_, ref tok)] if is_keyword(keywords::False, tok) => {
|
||||||
let mut rust_parser = Parser(sess, cfg.clone(), tt_rdr.dup());
|
cx.set_trace_macros(false);
|
||||||
|
}
|
||||||
if rust_parser.is_keyword(keywords::True) {
|
_ => cx.span_err(sp, "trace_macros! accepts only `true` or `false`"),
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
rust_parser.bump();
|
base::MacResult::dummy_any(sp)
|
||||||
|
|
||||||
let mut rust_parser = Parser(sess, cfg, tt_rdr.dup());
|
|
||||||
let result = rust_parser.parse_expr();
|
|
||||||
base::MRExpr(result)
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,5 +15,4 @@ fn main() {
|
|||||||
|
|
||||||
concat!(test!());
|
concat!(test!());
|
||||||
//~^ ERROR: macro undefined: 'test'
|
//~^ ERROR: macro undefined: 'test'
|
||||||
//~^^ ERROR: expected a literal
|
|
||||||
}
|
}
|
||||||
|
|||||||
29
src/test/compile-fail/trace_macros-format.rs
Normal file
29
src/test/compile-fail/trace_macros-format.rs
Normal file
@@ -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);
|
||||||
|
}
|
||||||
30
src/test/run-pass/log_syntax-trace_macros-macro-locations.rs
Normal file
30
src/test/run-pass/log_syntax-trace_macros-macro-locations.rs
Normal file
@@ -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!());
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user