auto merge of #13527 : huonw/rust/macro-expander-trait, r=sfackler
There's now one unified way to return things from a macro, instead of being able to choose the `AnyMacro` trait or the `MRItem`/`MRExpr` variants of the `MacResult` enum. This does simplify the logic handling the expansions, but the biggest value of this is it makes macros in (for example) type position easier to implement, as there's this single thing to modify. By my measurements (using `-Z time-passes` on libstd and librustc etc.), this appears to have little-to-no impact on expansion speed. There are presumably larger costs than the small number of extra allocations and virtual calls this adds (notably, all `macro_rules!`-defined macros have not changed in behaviour, since they had to use the `AnyMacro` trait anyway). --- Summary of changes for dynamic syntax extension maintainers: - `MacResult` is now a trait, and is returned as `~MacResult` - `MRExpr` & `MRItem` are now `MacExpr::new` and `MacItem:new` respectively (which return `~MacResult`s) - `MacResult::dummy_...` is `DummyResult::any` or `DummyResult::expr`
This commit is contained in:
commit
61f788c772
@ -57,7 +57,7 @@ use syntax::ast::Name;
|
||||
use syntax::attr::contains;
|
||||
use syntax::codemap::{Span, mk_sp};
|
||||
use syntax::ext::base;
|
||||
use syntax::ext::base::{SyntaxExtension, BasicMacroExpander, NormalTT, ExtCtxt, MRExpr};
|
||||
use syntax::ext::base::{SyntaxExtension, BasicMacroExpander, NormalTT, ExtCtxt, MacExpr};
|
||||
use syntax::ext::build::AstBuilder;
|
||||
use syntax::parse;
|
||||
use syntax::parse::token;
|
||||
@ -73,7 +73,7 @@ pub fn macro_registrar(register: |Name, SyntaxExtension|) {
|
||||
None));
|
||||
}
|
||||
|
||||
pub fn expand_syntax_ext(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) -> base::MacResult {
|
||||
pub fn expand_syntax_ext(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) -> ~base::MacResult {
|
||||
let (expr, endian) = parse_tts(cx, tts);
|
||||
|
||||
let little = match endian {
|
||||
@ -101,12 +101,12 @@ pub fn expand_syntax_ext(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) ->
|
||||
}
|
||||
_ => {
|
||||
cx.span_err(expr.span, "unsupported literal in fourcc!");
|
||||
return MRExpr(cx.expr_lit(sp, ast::LitUint(0u64, ast::TyU32)));
|
||||
return base::DummyResult::expr(sp)
|
||||
}
|
||||
},
|
||||
_ => {
|
||||
cx.span_err(expr.span, "non-literal in fourcc!");
|
||||
return MRExpr(cx.expr_lit(sp, ast::LitUint(0u64, ast::TyU32)));
|
||||
return base::DummyResult::expr(sp)
|
||||
}
|
||||
};
|
||||
|
||||
@ -126,7 +126,7 @@ pub fn expand_syntax_ext(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) ->
|
||||
};
|
||||
}
|
||||
let e = cx.expr_lit(sp, ast::LitUint(val as u64, ast::TyU32));
|
||||
MRExpr(e)
|
||||
MacExpr::new(e)
|
||||
}
|
||||
|
||||
struct Ident {
|
||||
|
@ -53,7 +53,7 @@ use syntax::ast;
|
||||
use syntax::ast::Name;
|
||||
use syntax::codemap::{Span, mk_sp};
|
||||
use syntax::ext::base;
|
||||
use syntax::ext::base::{SyntaxExtension, BasicMacroExpander, NormalTT, ExtCtxt, MRExpr};
|
||||
use syntax::ext::base::{SyntaxExtension, BasicMacroExpander, NormalTT, ExtCtxt, MacExpr};
|
||||
use syntax::ext::build::AstBuilder;
|
||||
use syntax::parse;
|
||||
use syntax::parse::token;
|
||||
@ -97,7 +97,7 @@ fn hex_float_lit_err(s: &str) -> Option<(uint, ~str)> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn expand_syntax_ext(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) -> base::MacResult {
|
||||
pub fn expand_syntax_ext(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) -> ~base::MacResult {
|
||||
let (expr, ty_lit) = parse_tts(cx, tts);
|
||||
|
||||
let ty = match ty_lit {
|
||||
@ -121,12 +121,12 @@ pub fn expand_syntax_ext(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) ->
|
||||
}
|
||||
_ => {
|
||||
cx.span_err(expr.span, "unsupported literal in hexfloat!");
|
||||
return base::MacResult::dummy_expr(sp);
|
||||
return base::DummyResult::expr(sp);
|
||||
}
|
||||
},
|
||||
_ => {
|
||||
cx.span_err(expr.span, "non-literal in hexfloat!");
|
||||
return base::MacResult::dummy_expr(sp);
|
||||
return base::DummyResult::expr(sp);
|
||||
}
|
||||
};
|
||||
|
||||
@ -137,7 +137,7 @@ pub fn expand_syntax_ext(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) ->
|
||||
let pos = expr.span.lo + syntax::codemap::Pos::from_uint(err_pos + 1);
|
||||
let span = syntax::codemap::mk_sp(pos,pos);
|
||||
cx.span_err(span, format!("invalid hex float literal in hexfloat!: {}", err_str));
|
||||
return base::MacResult::dummy_expr(sp);
|
||||
return base::DummyResult::expr(sp);
|
||||
}
|
||||
_ => ()
|
||||
}
|
||||
@ -147,7 +147,7 @@ pub fn expand_syntax_ext(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) ->
|
||||
None => ast::LitFloatUnsuffixed(s),
|
||||
Some (ty) => ast::LitFloat(s, ty)
|
||||
};
|
||||
MRExpr(cx.expr_lit(sp, lit))
|
||||
MacExpr::new(cx.expr_lit(sp, lit))
|
||||
}
|
||||
|
||||
struct Ident {
|
||||
|
@ -45,7 +45,7 @@ impl State {
|
||||
static OPTIONS: &'static [&'static str] = &["volatile", "alignstack", "intel"];
|
||||
|
||||
pub fn expand_asm(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
|
||||
-> base::MacResult {
|
||||
-> ~base::MacResult {
|
||||
let mut p = parse::new_parser_from_tts(cx.parse_sess(),
|
||||
cx.cfg(),
|
||||
tts.iter()
|
||||
@ -72,7 +72,7 @@ pub fn expand_asm(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
|
||||
"inline assembly must be a string literal.") {
|
||||
Some((s, st)) => (s, st),
|
||||
// let compilation continue
|
||||
None => return MacResult::dummy_expr(sp),
|
||||
None => return DummyResult::expr(sp),
|
||||
};
|
||||
asm = s;
|
||||
asm_str_style = Some(style);
|
||||
@ -210,7 +210,7 @@ pub fn expand_asm(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
|
||||
inputs.push((token::intern_and_get_ident(i.to_str()), out));
|
||||
}
|
||||
|
||||
MRExpr(@ast::Expr {
|
||||
MacExpr::new(@ast::Expr {
|
||||
id: ast::DUMMY_NODE_ID,
|
||||
node: ast::ExprInlineAsm(ast::InlineAsm {
|
||||
asm: token::intern_and_get_ident(asm.get()),
|
||||
|
@ -50,19 +50,19 @@ pub trait MacroExpander {
|
||||
ecx: &mut ExtCtxt,
|
||||
span: Span,
|
||||
token_tree: &[ast::TokenTree])
|
||||
-> MacResult;
|
||||
-> ~MacResult;
|
||||
}
|
||||
|
||||
pub type MacroExpanderFn =
|
||||
fn(ecx: &mut ExtCtxt, span: codemap::Span, token_tree: &[ast::TokenTree])
|
||||
-> MacResult;
|
||||
-> ~MacResult;
|
||||
|
||||
impl MacroExpander for BasicMacroExpander {
|
||||
fn expand(&self,
|
||||
ecx: &mut ExtCtxt,
|
||||
span: Span,
|
||||
token_tree: &[ast::TokenTree])
|
||||
-> MacResult {
|
||||
-> ~MacResult {
|
||||
(self.expander)(ecx, span, token_tree)
|
||||
}
|
||||
}
|
||||
@ -78,7 +78,7 @@ pub trait IdentMacroExpander {
|
||||
sp: Span,
|
||||
ident: ast::Ident,
|
||||
token_tree: Vec<ast::TokenTree> )
|
||||
-> MacResult;
|
||||
-> ~MacResult;
|
||||
}
|
||||
|
||||
impl IdentMacroExpander for BasicIdentMacroExpander {
|
||||
@ -87,62 +87,130 @@ impl IdentMacroExpander for BasicIdentMacroExpander {
|
||||
sp: Span,
|
||||
ident: ast::Ident,
|
||||
token_tree: Vec<ast::TokenTree> )
|
||||
-> MacResult {
|
||||
-> ~MacResult {
|
||||
(self.expander)(cx, sp, ident, token_tree)
|
||||
}
|
||||
}
|
||||
|
||||
pub type IdentMacroExpanderFn =
|
||||
fn(&mut ExtCtxt, Span, ast::Ident, Vec<ast::TokenTree> ) -> MacResult;
|
||||
fn(&mut ExtCtxt, Span, ast::Ident, Vec<ast::TokenTree> ) -> ~MacResult;
|
||||
|
||||
pub type MacroCrateRegistrationFun =
|
||||
fn(|ast::Name, SyntaxExtension|);
|
||||
|
||||
pub trait AnyMacro {
|
||||
fn make_expr(&self) -> @ast::Expr;
|
||||
fn make_items(&self) -> SmallVector<@ast::Item>;
|
||||
fn make_stmt(&self) -> @ast::Stmt;
|
||||
/// The result of a macro expansion. The return values of the various
|
||||
/// methods are spliced into the AST at the callsite of the macro (or
|
||||
/// just into the compiler's internal macro table, for `make_def`).
|
||||
pub trait MacResult {
|
||||
/// Define a new macro.
|
||||
fn make_def(&self) -> Option<MacroDef> {
|
||||
None
|
||||
}
|
||||
/// Create an expression.
|
||||
fn make_expr(&self) -> Option<@ast::Expr> {
|
||||
None
|
||||
}
|
||||
/// Create zero or more items.
|
||||
fn make_items(&self) -> Option<SmallVector<@ast::Item>> {
|
||||
None
|
||||
}
|
||||
|
||||
/// Create a statement.
|
||||
///
|
||||
/// By default this attempts to create an expression statement,
|
||||
/// returning None if that fails.
|
||||
fn make_stmt(&self) -> Option<@ast::Stmt> {
|
||||
self.make_expr()
|
||||
.map(|e| @codemap::respan(e.span, ast::StmtExpr(e, ast::DUMMY_NODE_ID)))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pub enum MacResult {
|
||||
MRExpr(@ast::Expr),
|
||||
MRItem(@ast::Item),
|
||||
MRAny(~AnyMacro:),
|
||||
MRDef(MacroDef),
|
||||
/// A convenience type for macros that return a single expression.
|
||||
pub struct MacExpr {
|
||||
e: @ast::Expr
|
||||
}
|
||||
impl MacResult {
|
||||
/// Create an empty expression MacResult; useful for satisfying
|
||||
/// type signatures after emitting a non-fatal error (which stop
|
||||
/// compilation well before the validity (or otherwise)) of the
|
||||
/// expression are checked.
|
||||
pub fn raw_dummy_expr(sp: codemap::Span) -> @ast::Expr {
|
||||
impl MacExpr {
|
||||
pub fn new(e: @ast::Expr) -> ~MacResult {
|
||||
~MacExpr { e: e } as ~MacResult
|
||||
}
|
||||
}
|
||||
impl MacResult for MacExpr {
|
||||
fn make_expr(&self) -> Option<@ast::Expr> {
|
||||
Some(self.e)
|
||||
}
|
||||
}
|
||||
/// A convenience type for macros that return a single item.
|
||||
pub struct MacItem {
|
||||
i: @ast::Item
|
||||
}
|
||||
impl MacItem {
|
||||
pub fn new(i: @ast::Item) -> ~MacResult {
|
||||
~MacItem { i: i } as ~MacResult
|
||||
}
|
||||
}
|
||||
impl MacResult for MacItem {
|
||||
fn make_items(&self) -> Option<SmallVector<@ast::Item>> {
|
||||
Some(SmallVector::one(self.i))
|
||||
}
|
||||
fn make_stmt(&self) -> Option<@ast::Stmt> {
|
||||
Some(@codemap::respan(
|
||||
self.i.span,
|
||||
ast::StmtDecl(
|
||||
@codemap::respan(self.i.span, ast::DeclItem(self.i)),
|
||||
ast::DUMMY_NODE_ID)))
|
||||
}
|
||||
}
|
||||
|
||||
/// Fill-in macro expansion result, to allow compilation to continue
|
||||
/// after hitting errors.
|
||||
pub struct DummyResult {
|
||||
expr_only: bool,
|
||||
span: Span
|
||||
}
|
||||
|
||||
impl DummyResult {
|
||||
/// Create a default MacResult that can be anything.
|
||||
///
|
||||
/// Use this as a return value after hitting any errors and
|
||||
/// calling `span_err`.
|
||||
pub fn any(sp: Span) -> ~MacResult {
|
||||
~DummyResult { expr_only: false, span: sp } as ~MacResult
|
||||
}
|
||||
|
||||
/// Create a default MacResult that can only be an expression.
|
||||
///
|
||||
/// Use this for macros that must expand to an expression, so even
|
||||
/// if an error is encountered internally, the user will recieve
|
||||
/// an error that they also used it in the wrong place.
|
||||
pub fn expr(sp: Span) -> ~MacResult {
|
||||
~DummyResult { expr_only: true, span: sp } as ~MacResult
|
||||
}
|
||||
|
||||
/// A plain dummy expression.
|
||||
pub fn raw_expr(sp: Span) -> @ast::Expr {
|
||||
@ast::Expr {
|
||||
id: ast::DUMMY_NODE_ID,
|
||||
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)
|
||||
|
||||
impl MacResult for DummyResult {
|
||||
fn make_expr(&self) -> Option<@ast::Expr> {
|
||||
Some(DummyResult::raw_expr(self.span))
|
||||
}
|
||||
fn make_items(&self) -> SmallVector<@ast::Item> {
|
||||
SmallVector::zero()
|
||||
fn make_items(&self) -> Option<SmallVector<@ast::Item>> {
|
||||
if self.expr_only {
|
||||
None
|
||||
} else {
|
||||
Some(SmallVector::zero())
|
||||
}
|
||||
}
|
||||
fn make_stmt(&self) -> @ast::Stmt {
|
||||
@codemap::respan(self.sp,
|
||||
ast::StmtExpr(MacResult::raw_dummy_expr(self.sp), ast::DUMMY_NODE_ID))
|
||||
fn make_stmt(&self) -> Option<@ast::Stmt> {
|
||||
Some(@codemap::respan(self.span,
|
||||
ast::StmtExpr(DummyResult::raw_expr(self.span),
|
||||
ast::DUMMY_NODE_ID)))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -18,10 +18,10 @@ use ext::build::AstBuilder;
|
||||
|
||||
use std::char;
|
||||
|
||||
pub fn expand_syntax_ext(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) -> base::MacResult {
|
||||
pub fn expand_syntax_ext(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) -> ~base::MacResult {
|
||||
// Gather all argument expressions
|
||||
let exprs = match get_exprs_from_tts(cx, sp, tts) {
|
||||
None => return MacResult::dummy_expr(sp),
|
||||
None => return DummyResult::expr(sp),
|
||||
Some(e) => e,
|
||||
};
|
||||
let mut bytes = Vec::new();
|
||||
@ -74,5 +74,5 @@ pub fn expand_syntax_ext(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) ->
|
||||
}
|
||||
|
||||
let e = cx.expr_vec_slice(sp, bytes);
|
||||
MRExpr(e)
|
||||
MacExpr::new(e)
|
||||
}
|
||||
|
@ -26,7 +26,7 @@ use parse::token::InternedString;
|
||||
use parse::token;
|
||||
use parse;
|
||||
|
||||
pub fn expand_cfg(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) -> base::MacResult {
|
||||
pub fn expand_cfg(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) -> ~base::MacResult {
|
||||
let mut p = parse::new_parser_from_tts(cx.parse_sess(),
|
||||
cx.cfg(),
|
||||
tts.iter()
|
||||
@ -47,5 +47,5 @@ pub fn expand_cfg(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) -> base::M
|
||||
let matches_cfg = attr::test_cfg(cx.cfg().as_slice(),
|
||||
in_cfg.iter().map(|&x| x));
|
||||
let e = cx.expr_bool(sp, matches_cfg);
|
||||
MRExpr(e)
|
||||
MacExpr::new(e)
|
||||
}
|
||||
|
@ -19,10 +19,10 @@ use std::strbuf::StrBuf;
|
||||
|
||||
pub fn expand_syntax_ext(cx: &mut base::ExtCtxt,
|
||||
sp: codemap::Span,
|
||||
tts: &[ast::TokenTree]) -> base::MacResult {
|
||||
tts: &[ast::TokenTree]) -> ~base::MacResult {
|
||||
let es = match base::get_exprs_from_tts(cx, sp, tts) {
|
||||
Some(e) => e,
|
||||
None => return base::MacResult::dummy_expr(sp)
|
||||
None => return base::DummyResult::expr(sp)
|
||||
};
|
||||
let mut accumulator = StrBuf::new();
|
||||
for e in es.move_iter() {
|
||||
@ -57,7 +57,7 @@ pub fn expand_syntax_ext(cx: &mut base::ExtCtxt,
|
||||
}
|
||||
}
|
||||
}
|
||||
base::MRExpr(cx.expr_str(
|
||||
base::MacExpr::new(cx.expr_str(
|
||||
sp,
|
||||
token::intern_and_get_ident(accumulator.into_owned())))
|
||||
}
|
||||
|
@ -19,7 +19,7 @@ use parse::token::{str_to_ident};
|
||||
use std::strbuf::StrBuf;
|
||||
|
||||
pub fn expand_syntax_ext(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
|
||||
-> base::MacResult {
|
||||
-> ~base::MacResult {
|
||||
let mut res_str = StrBuf::new();
|
||||
for (i, e) in tts.iter().enumerate() {
|
||||
if i & 1 == 1 {
|
||||
@ -27,7 +27,7 @@ pub fn expand_syntax_ext(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
|
||||
ast::TTTok(_, token::COMMA) => (),
|
||||
_ => {
|
||||
cx.span_err(sp, "concat_idents! expecting comma.");
|
||||
return MacResult::dummy_expr(sp);
|
||||
return DummyResult::expr(sp);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@ -37,7 +37,7 @@ pub fn expand_syntax_ext(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
|
||||
}
|
||||
_ => {
|
||||
cx.span_err(sp, "concat_idents! requires ident args.");
|
||||
return MacResult::dummy_expr(sp);
|
||||
return DummyResult::expr(sp);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -61,5 +61,5 @@ pub fn expand_syntax_ext(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
|
||||
),
|
||||
span: sp,
|
||||
};
|
||||
MRExpr(e)
|
||||
MacExpr::new(e)
|
||||
}
|
||||
|
@ -24,9 +24,9 @@ use parse::token;
|
||||
use std::os;
|
||||
|
||||
pub fn expand_option_env(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
|
||||
-> base::MacResult {
|
||||
-> ~base::MacResult {
|
||||
let var = match get_single_str_from_tts(cx, sp, tts, "option_env!") {
|
||||
None => return MacResult::dummy_expr(sp),
|
||||
None => return DummyResult::expr(sp),
|
||||
Some(v) => v
|
||||
};
|
||||
|
||||
@ -56,24 +56,24 @@ pub fn expand_option_env(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
|
||||
s))))
|
||||
}
|
||||
};
|
||||
MRExpr(e)
|
||||
MacExpr::new(e)
|
||||
}
|
||||
|
||||
pub fn expand_env(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
|
||||
-> base::MacResult {
|
||||
-> ~base::MacResult {
|
||||
let exprs = match get_exprs_from_tts(cx, sp, tts) {
|
||||
Some(ref exprs) if exprs.len() == 0 => {
|
||||
cx.span_err(sp, "env! takes 1 or 2 arguments");
|
||||
return MacResult::dummy_expr(sp);
|
||||
return DummyResult::expr(sp);
|
||||
}
|
||||
None => return MacResult::dummy_expr(sp),
|
||||
None => return DummyResult::expr(sp),
|
||||
Some(exprs) => exprs
|
||||
};
|
||||
|
||||
let var = match expr_to_str(cx,
|
||||
*exprs.get(0),
|
||||
"expected string literal") {
|
||||
None => return MacResult::dummy_expr(sp),
|
||||
None => return DummyResult::expr(sp),
|
||||
Some((v, _style)) => v
|
||||
};
|
||||
let msg = match exprs.len() {
|
||||
@ -84,13 +84,13 @@ pub fn expand_env(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
|
||||
}
|
||||
2 => {
|
||||
match expr_to_str(cx, *exprs.get(1), "expected string literal") {
|
||||
None => return MacResult::dummy_expr(sp),
|
||||
None => return DummyResult::expr(sp),
|
||||
Some((s, _style)) => s
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
cx.span_err(sp, "env! takes 1 or 2 arguments");
|
||||
return MacResult::dummy_expr(sp);
|
||||
return DummyResult::expr(sp);
|
||||
}
|
||||
};
|
||||
|
||||
@ -101,5 +101,5 @@ pub fn expand_env(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
|
||||
}
|
||||
Some(s) => cx.expr_str(sp, token::intern_and_get_ident(s))
|
||||
};
|
||||
MRExpr(e)
|
||||
MacExpr::new(e)
|
||||
}
|
||||
|
@ -52,7 +52,7 @@ pub fn expand_expr(e: @ast::Expr, fld: &mut MacroExpander) -> @ast::Expr {
|
||||
format!("expected macro name without module \
|
||||
separators"));
|
||||
// let compilation continue
|
||||
return MacResult::raw_dummy_expr(e.span);
|
||||
return DummyResult::raw_expr(e.span);
|
||||
}
|
||||
let extname = pth.segments.get(0).identifier;
|
||||
let extnamestr = token::get_ident(extname);
|
||||
@ -65,7 +65,7 @@ pub fn expand_expr(e: @ast::Expr, fld: &mut MacroExpander) -> @ast::Expr {
|
||||
extnamestr.get()));
|
||||
|
||||
// let compilation continue
|
||||
return MacResult::raw_dummy_expr(e.span);
|
||||
return DummyResult::raw_expr(e.span);
|
||||
}
|
||||
Some(&NormalTT(ref expandfun, exp_span)) => {
|
||||
fld.cx.bt_push(ExpnInfo {
|
||||
@ -88,10 +88,9 @@ pub fn expand_expr(e: @ast::Expr, fld: &mut MacroExpander) -> @ast::Expr {
|
||||
|
||||
let expanded = match expandfun.expand(fld.cx,
|
||||
mac_span.call_site,
|
||||
marked_before.as_slice()) {
|
||||
MRExpr(e) => e,
|
||||
MRAny(any_macro) => any_macro.make_expr(),
|
||||
_ => {
|
||||
marked_before.as_slice()).make_expr() {
|
||||
Some(e) => e,
|
||||
None => {
|
||||
fld.cx.span_err(
|
||||
pth.span,
|
||||
format!(
|
||||
@ -99,7 +98,7 @@ pub fn expand_expr(e: @ast::Expr, fld: &mut MacroExpander) -> @ast::Expr {
|
||||
extnamestr.get()
|
||||
)
|
||||
);
|
||||
return MacResult::raw_dummy_expr(e.span);
|
||||
return DummyResult::raw_expr(e.span);
|
||||
}
|
||||
};
|
||||
|
||||
@ -112,7 +111,7 @@ pub fn expand_expr(e: @ast::Expr, fld: &mut MacroExpander) -> @ast::Expr {
|
||||
format!("'{}' is not a tt-style macro",
|
||||
extnamestr.get())
|
||||
);
|
||||
return MacResult::raw_dummy_expr(e.span);
|
||||
return DummyResult::raw_expr(e.span);
|
||||
}
|
||||
};
|
||||
|
||||
@ -430,25 +429,8 @@ pub fn expand_item_mac(it: @ast::Item, fld: &mut MacroExpander)
|
||||
}
|
||||
};
|
||||
|
||||
let items = match expanded {
|
||||
MRItem(it) => {
|
||||
mark_item(it,fm).move_iter()
|
||||
.flat_map(|i| fld.fold_item(i).move_iter())
|
||||
.collect()
|
||||
}
|
||||
MRExpr(_) => {
|
||||
fld.cx.span_err(pth.span,
|
||||
format!("expr macro in item position: {}",
|
||||
extnamestr.get()));
|
||||
return SmallVector::zero();
|
||||
}
|
||||
MRAny(any_macro) => {
|
||||
any_macro.make_items().move_iter()
|
||||
.flat_map(|i| mark_item(i, fm).move_iter())
|
||||
.flat_map(|i| fld.fold_item(i).move_iter())
|
||||
.collect()
|
||||
}
|
||||
MRDef(MacroDef { name, ext }) => {
|
||||
let items = match expanded.make_def() {
|
||||
Some(MacroDef { name, ext }) => {
|
||||
// yikes... no idea how to apply the mark to this. I'm afraid
|
||||
// we're going to have to wait-and-see on this one.
|
||||
fld.extsbox.insert(intern(name), ext);
|
||||
@ -458,6 +440,22 @@ pub fn expand_item_mac(it: @ast::Item, fld: &mut MacroExpander)
|
||||
SmallVector::zero()
|
||||
}
|
||||
}
|
||||
None => {
|
||||
match expanded.make_items() {
|
||||
Some(items) => {
|
||||
items.move_iter()
|
||||
.flat_map(|i| mark_item(i, fm).move_iter())
|
||||
.flat_map(|i| fld.fold_item(i).move_iter())
|
||||
.collect()
|
||||
}
|
||||
None => {
|
||||
fld.cx.span_err(pth.span,
|
||||
format!("expr macro in item position: {}",
|
||||
extnamestr.get()));
|
||||
return SmallVector::zero();
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
fld.cx.bt_pop();
|
||||
return items;
|
||||
@ -593,15 +591,9 @@ pub fn expand_stmt(s: &Stmt, fld: &mut MacroExpander) -> SmallVector<@Stmt> {
|
||||
|
||||
let expanded = match expandfun.expand(fld.cx,
|
||||
mac_span.call_site,
|
||||
marked_tts.as_slice()) {
|
||||
MRExpr(e) => {
|
||||
@codemap::Spanned {
|
||||
node: StmtExpr(e, ast::DUMMY_NODE_ID),
|
||||
span: e.span,
|
||||
}
|
||||
}
|
||||
MRAny(any_macro) => any_macro.make_stmt(),
|
||||
_ => {
|
||||
marked_tts.as_slice()).make_stmt() {
|
||||
Some(stmt) => stmt,
|
||||
None => {
|
||||
fld.cx.span_err(pth.span,
|
||||
format!("non-stmt macro in stmt pos: {}",
|
||||
extnamestr));
|
||||
|
@ -16,11 +16,11 @@ use ext::base;
|
||||
use ext::build::AstBuilder;
|
||||
|
||||
pub fn expand_syntax_ext(ecx: &mut base::ExtCtxt, sp: Span,
|
||||
_tts: &[ast::TokenTree]) -> base::MacResult {
|
||||
_tts: &[ast::TokenTree]) -> ~base::MacResult {
|
||||
ecx.span_err(sp, "`fmt!` is deprecated, use `format!` instead");
|
||||
ecx.parse_sess.span_diagnostic.span_note(sp,
|
||||
"see http://static.rust-lang.org/doc/master/std/fmt/index.html \
|
||||
for documentation");
|
||||
|
||||
base::MRExpr(ecx.expr_uint(sp, 2))
|
||||
base::MacExpr::new(ecx.expr_uint(sp, 2))
|
||||
}
|
||||
|
@ -806,14 +806,14 @@ impl<'a, 'b> Context<'a, 'b> {
|
||||
}
|
||||
|
||||
pub fn expand_args(ecx: &mut ExtCtxt, sp: Span,
|
||||
tts: &[ast::TokenTree]) -> base::MacResult {
|
||||
tts: &[ast::TokenTree]) -> ~base::MacResult {
|
||||
|
||||
match parse_args(ecx, sp, tts) {
|
||||
(extra, Some((efmt, args, order, names))) => {
|
||||
MRExpr(expand_preparsed_format_args(ecx, sp, extra, efmt, args,
|
||||
MacExpr::new(expand_preparsed_format_args(ecx, sp, extra, efmt, args,
|
||||
order, names))
|
||||
}
|
||||
(_, None) => MRExpr(ecx.expr_uint(sp, 2))
|
||||
(_, None) => MacExpr::new(ecx.expr_uint(sp, 2))
|
||||
}
|
||||
}
|
||||
|
||||
@ -845,7 +845,7 @@ pub fn expand_preparsed_format_args(ecx: &mut ExtCtxt, sp: Span,
|
||||
efmt,
|
||||
"format argument must be a string literal.") {
|
||||
Some((fmt, _)) => fmt,
|
||||
None => return MacResult::raw_dummy_expr(sp)
|
||||
None => return DummyResult::raw_expr(sp)
|
||||
};
|
||||
|
||||
let mut parser = parse::Parser::new(fmt.get());
|
||||
@ -863,7 +863,7 @@ pub fn expand_preparsed_format_args(ecx: &mut ExtCtxt, sp: Span,
|
||||
match parser.errors.shift() {
|
||||
Some(error) => {
|
||||
cx.ecx.span_err(efmt.span, "invalid format string: " + error);
|
||||
return MacResult::raw_dummy_expr(sp);
|
||||
return DummyResult::raw_expr(sp);
|
||||
}
|
||||
None => {}
|
||||
}
|
||||
|
@ -18,12 +18,12 @@ use std::rc::Rc;
|
||||
pub fn expand_syntax_ext(cx: &mut base::ExtCtxt,
|
||||
sp: codemap::Span,
|
||||
tt: &[ast::TokenTree])
|
||||
-> base::MacResult {
|
||||
-> ~base::MacResult {
|
||||
|
||||
cx.print_backtrace();
|
||||
println!("{}", print::pprust::tt_to_str(&ast::TTDelim(
|
||||
Rc::new(tt.iter().map(|x| (*x).clone()).collect()))));
|
||||
|
||||
// any so that `log_syntax` can be invoked as an expression and item.
|
||||
base::MacResult::dummy_any(sp)
|
||||
base::DummyResult::any(sp)
|
||||
}
|
||||
|
@ -289,53 +289,53 @@ pub mod rt {
|
||||
|
||||
pub fn expand_quote_tokens(cx: &mut ExtCtxt,
|
||||
sp: Span,
|
||||
tts: &[ast::TokenTree]) -> base::MacResult {
|
||||
tts: &[ast::TokenTree]) -> ~base::MacResult {
|
||||
let (cx_expr, expr) = expand_tts(cx, sp, tts);
|
||||
let expanded = expand_wrapper(cx, sp, cx_expr, expr);
|
||||
base::MRExpr(expanded)
|
||||
base::MacExpr::new(expanded)
|
||||
}
|
||||
|
||||
pub fn expand_quote_expr(cx: &mut ExtCtxt,
|
||||
sp: Span,
|
||||
tts: &[ast::TokenTree]) -> base::MacResult {
|
||||
tts: &[ast::TokenTree]) -> ~base::MacResult {
|
||||
let expanded = expand_parse_call(cx, sp, "parse_expr", Vec::new(), tts);
|
||||
base::MRExpr(expanded)
|
||||
base::MacExpr::new(expanded)
|
||||
}
|
||||
|
||||
pub fn expand_quote_item(cx: &mut ExtCtxt,
|
||||
sp: Span,
|
||||
tts: &[ast::TokenTree]) -> base::MacResult {
|
||||
tts: &[ast::TokenTree]) -> ~base::MacResult {
|
||||
let e_attrs = cx.expr_vec_ng(sp);
|
||||
let expanded = expand_parse_call(cx, sp, "parse_item",
|
||||
vec!(e_attrs), tts);
|
||||
base::MRExpr(expanded)
|
||||
base::MacExpr::new(expanded)
|
||||
}
|
||||
|
||||
pub fn expand_quote_pat(cx: &mut ExtCtxt,
|
||||
sp: Span,
|
||||
tts: &[ast::TokenTree]) -> base::MacResult {
|
||||
tts: &[ast::TokenTree]) -> ~base::MacResult {
|
||||
let e_refutable = cx.expr_lit(sp, ast::LitBool(true));
|
||||
let expanded = expand_parse_call(cx, sp, "parse_pat",
|
||||
vec!(e_refutable), tts);
|
||||
base::MRExpr(expanded)
|
||||
base::MacExpr::new(expanded)
|
||||
}
|
||||
|
||||
pub fn expand_quote_ty(cx: &mut ExtCtxt,
|
||||
sp: Span,
|
||||
tts: &[ast::TokenTree]) -> base::MacResult {
|
||||
tts: &[ast::TokenTree]) -> ~base::MacResult {
|
||||
let e_param_colons = cx.expr_lit(sp, ast::LitBool(false));
|
||||
let expanded = expand_parse_call(cx, sp, "parse_ty",
|
||||
vec!(e_param_colons), tts);
|
||||
base::MRExpr(expanded)
|
||||
base::MacExpr::new(expanded)
|
||||
}
|
||||
|
||||
pub fn expand_quote_stmt(cx: &mut ExtCtxt,
|
||||
sp: Span,
|
||||
tts: &[ast::TokenTree]) -> base::MacResult {
|
||||
tts: &[ast::TokenTree]) -> ~base::MacResult {
|
||||
let e_attrs = cx.expr_vec_ng(sp);
|
||||
let expanded = expand_parse_call(cx, sp, "parse_stmt",
|
||||
vec!(e_attrs), tts);
|
||||
base::MRExpr(expanded)
|
||||
base::MacExpr::new(expanded)
|
||||
}
|
||||
|
||||
fn ids_ext(strs: Vec<~str> ) -> Vec<ast::Ident> {
|
||||
|
@ -29,63 +29,63 @@ use std::str;
|
||||
|
||||
/* line!(): expands to the current line number */
|
||||
pub fn expand_line(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
|
||||
-> base::MacResult {
|
||||
-> ~base::MacResult {
|
||||
base::check_zero_tts(cx, sp, tts, "line!");
|
||||
|
||||
let topmost = topmost_expn_info(cx.backtrace().unwrap());
|
||||
let loc = cx.codemap().lookup_char_pos(topmost.call_site.lo);
|
||||
|
||||
base::MRExpr(cx.expr_uint(topmost.call_site, loc.line))
|
||||
base::MacExpr::new(cx.expr_uint(topmost.call_site, loc.line))
|
||||
}
|
||||
|
||||
/* col!(): expands to the current column number */
|
||||
pub fn expand_col(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
|
||||
-> base::MacResult {
|
||||
-> ~base::MacResult {
|
||||
base::check_zero_tts(cx, sp, tts, "col!");
|
||||
|
||||
let topmost = topmost_expn_info(cx.backtrace().unwrap());
|
||||
let loc = cx.codemap().lookup_char_pos(topmost.call_site.lo);
|
||||
base::MRExpr(cx.expr_uint(topmost.call_site, loc.col.to_uint()))
|
||||
base::MacExpr::new(cx.expr_uint(topmost.call_site, loc.col.to_uint()))
|
||||
}
|
||||
|
||||
/* file!(): expands to the current filename */
|
||||
/* The filemap (`loc.file`) contains a bunch more information we could spit
|
||||
* out if we wanted. */
|
||||
pub fn expand_file(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
|
||||
-> base::MacResult {
|
||||
-> ~base::MacResult {
|
||||
base::check_zero_tts(cx, sp, tts, "file!");
|
||||
|
||||
let topmost = topmost_expn_info(cx.backtrace().unwrap());
|
||||
let loc = cx.codemap().lookup_char_pos(topmost.call_site.lo);
|
||||
let filename = token::intern_and_get_ident(loc.file.name);
|
||||
base::MRExpr(cx.expr_str(topmost.call_site, filename))
|
||||
base::MacExpr::new(cx.expr_str(topmost.call_site, filename))
|
||||
}
|
||||
|
||||
pub fn expand_stringify(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
|
||||
-> base::MacResult {
|
||||
-> ~base::MacResult {
|
||||
let s = pprust::tts_to_str(tts);
|
||||
base::MRExpr(cx.expr_str(sp, token::intern_and_get_ident(s)))
|
||||
base::MacExpr::new(cx.expr_str(sp, token::intern_and_get_ident(s)))
|
||||
}
|
||||
|
||||
pub fn expand_mod(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
|
||||
-> base::MacResult {
|
||||
-> ~base::MacResult {
|
||||
base::check_zero_tts(cx, sp, tts, "module_path!");
|
||||
let string = cx.mod_path()
|
||||
.iter()
|
||||
.map(|x| token::get_ident(*x).get().to_str())
|
||||
.collect::<Vec<~str>>()
|
||||
.connect("::");
|
||||
base::MRExpr(cx.expr_str(sp, token::intern_and_get_ident(string)))
|
||||
base::MacExpr::new(cx.expr_str(sp, token::intern_and_get_ident(string)))
|
||||
}
|
||||
|
||||
// include! : parse the given file as an expr
|
||||
// This is generally a bad idea because it's going to behave
|
||||
// unhygienically.
|
||||
pub fn expand_include(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
|
||||
-> base::MacResult {
|
||||
-> ~base::MacResult {
|
||||
let file = match get_single_str_from_tts(cx, sp, tts, "include!") {
|
||||
Some(f) => f,
|
||||
None => return MacResult::dummy_expr(sp),
|
||||
None => return DummyResult::expr(sp),
|
||||
};
|
||||
// The file will be added to the code map by the parser
|
||||
let mut p =
|
||||
@ -95,21 +95,21 @@ pub fn expand_include(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
|
||||
sp,
|
||||
&Path::new(file)),
|
||||
sp);
|
||||
base::MRExpr(p.parse_expr())
|
||||
base::MacExpr::new(p.parse_expr())
|
||||
}
|
||||
|
||||
// include_str! : read the given file, insert it as a literal string expr
|
||||
pub fn expand_include_str(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
|
||||
-> base::MacResult {
|
||||
-> ~base::MacResult {
|
||||
let file = match get_single_str_from_tts(cx, sp, tts, "include_str!") {
|
||||
Some(f) => f,
|
||||
None => return MacResult::dummy_expr(sp)
|
||||
None => return DummyResult::expr(sp)
|
||||
};
|
||||
let file = res_rel_file(cx, sp, &Path::new(file));
|
||||
let bytes = match File::open(&file).read_to_end() {
|
||||
Err(e) => {
|
||||
cx.span_err(sp, format!("couldn't read {}: {}", file.display(), e));
|
||||
return MacResult::dummy_expr(sp);
|
||||
return DummyResult::expr(sp);
|
||||
}
|
||||
Ok(bytes) => bytes,
|
||||
};
|
||||
@ -121,31 +121,31 @@ pub fn expand_include_str(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
|
||||
let interned = token::intern_and_get_ident(src);
|
||||
cx.codemap().new_filemap(filename, src.to_owned());
|
||||
|
||||
base::MRExpr(cx.expr_str(sp, interned))
|
||||
base::MacExpr::new(cx.expr_str(sp, interned))
|
||||
}
|
||||
None => {
|
||||
cx.span_err(sp, format!("{} wasn't a utf-8 file", file.display()));
|
||||
return MacResult::dummy_expr(sp);
|
||||
return DummyResult::expr(sp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn expand_include_bin(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
|
||||
-> base::MacResult
|
||||
-> ~base::MacResult
|
||||
{
|
||||
let file = match get_single_str_from_tts(cx, sp, tts, "include_bin!") {
|
||||
Some(f) => f,
|
||||
None => return MacResult::dummy_expr(sp)
|
||||
None => return DummyResult::expr(sp)
|
||||
};
|
||||
let file = res_rel_file(cx, sp, &Path::new(file));
|
||||
match File::open(&file).read_to_end() {
|
||||
Err(e) => {
|
||||
cx.span_err(sp, format!("couldn't read {}: {}", file.display(), e));
|
||||
return MacResult::dummy_expr(sp);
|
||||
return DummyResult::expr(sp);
|
||||
}
|
||||
Ok(bytes) => {
|
||||
let bytes = bytes.iter().map(|x| *x).collect();
|
||||
base::MRExpr(cx.expr_lit(sp, ast::LitBinary(Rc::new(bytes))))
|
||||
base::MacExpr::new(cx.expr_lit(sp, ast::LitBinary(Rc::new(bytes))))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -17,7 +17,7 @@ use parse::token::{keywords, is_keyword};
|
||||
pub fn expand_trace_macros(cx: &mut ExtCtxt,
|
||||
sp: Span,
|
||||
tt: &[ast::TokenTree])
|
||||
-> base::MacResult {
|
||||
-> ~base::MacResult {
|
||||
match tt {
|
||||
[ast::TTTok(_, ref tok)] if is_keyword(keywords::True, tok) => {
|
||||
cx.set_trace_macros(true);
|
||||
@ -28,5 +28,5 @@ pub fn expand_trace_macros(cx: &mut ExtCtxt,
|
||||
_ => cx.span_err(sp, "trace_macros! accepts only `true` or `false`"),
|
||||
}
|
||||
|
||||
base::MacResult::dummy_any(sp)
|
||||
base::DummyResult::any(sp)
|
||||
}
|
||||
|
@ -12,7 +12,7 @@ use ast::{Ident, Matcher_, Matcher, MatchTok, MatchNonterminal, MatchSeq};
|
||||
use ast::{TTDelim};
|
||||
use ast;
|
||||
use codemap::{Span, Spanned, DUMMY_SP};
|
||||
use ext::base::{AnyMacro, ExtCtxt, MacResult, MRAny, MRDef, MacroDef};
|
||||
use ext::base::{ExtCtxt, MacResult, MacroDef};
|
||||
use ext::base::{NormalTT, MacroExpander};
|
||||
use ext::base;
|
||||
use ext::tt::macro_parser::{Success, Error, Failure};
|
||||
@ -57,13 +57,13 @@ impl<'a> ParserAnyMacro<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> AnyMacro for ParserAnyMacro<'a> {
|
||||
fn make_expr(&self) -> @ast::Expr {
|
||||
impl<'a> MacResult for ParserAnyMacro<'a> {
|
||||
fn make_expr(&self) -> Option<@ast::Expr> {
|
||||
let ret = self.parser.borrow_mut().parse_expr();
|
||||
self.ensure_complete_parse(true);
|
||||
ret
|
||||
Some(ret)
|
||||
}
|
||||
fn make_items(&self) -> SmallVector<@ast::Item> {
|
||||
fn make_items(&self) -> Option<SmallVector<@ast::Item>> {
|
||||
let mut ret = SmallVector::zero();
|
||||
loop {
|
||||
let mut parser = self.parser.borrow_mut();
|
||||
@ -74,13 +74,13 @@ impl<'a> AnyMacro for ParserAnyMacro<'a> {
|
||||
}
|
||||
}
|
||||
self.ensure_complete_parse(false);
|
||||
ret
|
||||
Some(ret)
|
||||
}
|
||||
fn make_stmt(&self) -> @ast::Stmt {
|
||||
fn make_stmt(&self) -> Option<@ast::Stmt> {
|
||||
let attrs = self.parser.borrow_mut().parse_outer_attributes();
|
||||
let ret = self.parser.borrow_mut().parse_stmt(attrs);
|
||||
self.ensure_complete_parse(true);
|
||||
ret
|
||||
Some(ret)
|
||||
}
|
||||
}
|
||||
|
||||
@ -95,7 +95,7 @@ impl MacroExpander for MacroRulesMacroExpander {
|
||||
cx: &mut ExtCtxt,
|
||||
sp: Span,
|
||||
arg: &[ast::TokenTree])
|
||||
-> MacResult {
|
||||
-> ~MacResult {
|
||||
generic_extension(cx,
|
||||
sp,
|
||||
self.name,
|
||||
@ -105,6 +105,15 @@ impl MacroExpander for MacroRulesMacroExpander {
|
||||
}
|
||||
}
|
||||
|
||||
struct MacroRulesDefiner {
|
||||
def: RefCell<Option<MacroDef>>
|
||||
}
|
||||
impl MacResult for MacroRulesDefiner {
|
||||
fn make_def(&self) -> Option<MacroDef> {
|
||||
Some(self.def.borrow_mut().take().expect("MacroRulesDefiner expanded twice"))
|
||||
}
|
||||
}
|
||||
|
||||
// Given `lhses` and `rhses`, this is the new macro we create
|
||||
fn generic_extension(cx: &ExtCtxt,
|
||||
sp: Span,
|
||||
@ -112,7 +121,7 @@ fn generic_extension(cx: &ExtCtxt,
|
||||
arg: &[ast::TokenTree],
|
||||
lhses: &[Rc<NamedMatch>],
|
||||
rhses: &[Rc<NamedMatch>])
|
||||
-> MacResult {
|
||||
-> ~MacResult {
|
||||
if cx.trace_macros() {
|
||||
println!("{}! \\{ {} \\}",
|
||||
token::get_ident(name),
|
||||
@ -160,9 +169,9 @@ fn generic_extension(cx: &ExtCtxt,
|
||||
let p = Parser(cx.parse_sess(), cx.cfg(), ~trncbr);
|
||||
// Let the context choose how to interpret the result.
|
||||
// Weird, but useful for X-macros.
|
||||
return MRAny(~ParserAnyMacro {
|
||||
return ~ParserAnyMacro {
|
||||
parser: RefCell::new(p),
|
||||
})
|
||||
} as ~MacResult
|
||||
}
|
||||
Failure(sp, ref msg) => if sp.lo >= best_fail_spot.lo {
|
||||
best_fail_spot = sp;
|
||||
@ -184,7 +193,7 @@ pub fn add_new_extension(cx: &mut ExtCtxt,
|
||||
sp: Span,
|
||||
name: Ident,
|
||||
arg: Vec<ast::TokenTree> )
|
||||
-> base::MacResult {
|
||||
-> ~base::MacResult {
|
||||
// these spans won't matter, anyways
|
||||
fn ms(m: Matcher_) -> Matcher {
|
||||
Spanned {
|
||||
@ -236,8 +245,10 @@ pub fn add_new_extension(cx: &mut ExtCtxt,
|
||||
rhses: rhses,
|
||||
};
|
||||
|
||||
return MRDef(MacroDef {
|
||||
name: token::get_ident(name).to_str(),
|
||||
ext: NormalTT(exp, Some(sp))
|
||||
});
|
||||
~MacroRulesDefiner {
|
||||
def: RefCell::new(Some(MacroDef {
|
||||
name: token::get_ident(name).to_str(),
|
||||
ext: NormalTT(exp, Some(sp))
|
||||
}))
|
||||
} as ~MacResult
|
||||
}
|
||||
|
@ -35,11 +35,11 @@ pub fn macro_registrar(register: |Name, SyntaxExtension|) {
|
||||
register(token::intern("into_foo"), ItemModifier(expand_into_foo));
|
||||
}
|
||||
|
||||
fn expand_make_a_1(cx: &mut ExtCtxt, sp: Span, tts: &[TokenTree]) -> MacResult {
|
||||
fn expand_make_a_1(cx: &mut ExtCtxt, sp: Span, tts: &[TokenTree]) -> ~MacResult {
|
||||
if !tts.is_empty() {
|
||||
cx.span_fatal(sp, "make_a_1 takes no arguments");
|
||||
}
|
||||
MRExpr(quote_expr!(cx, 1i))
|
||||
MacExpr::new(quote_expr!(cx, 1i))
|
||||
}
|
||||
|
||||
fn expand_into_foo(cx: &mut ExtCtxt, sp: Span, attr: @MetaItem, it: @Item)
|
||||
|
Loading…
Reference in New Issue
Block a user