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:
commit
f8f60d80bf
@ -119,13 +119,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.
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -15,5 +15,4 @@ fn main() {
|
||||
|
||||
concat!(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!());
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user