libsyntax: Remove some more `@fn`s from the macro expander
This commit is contained in:
parent
6a8169db0a
commit
e95996399f
|
@ -33,62 +33,120 @@ pub struct MacroDef {
|
|||
ext: SyntaxExtension
|
||||
}
|
||||
|
||||
// No context arg for an Item Decorator macro, simply because
|
||||
// adding it would require adding a ctxt field to all items.
|
||||
// we could do this if it turns out to be useful.
|
||||
pub type ItemDecorator = extern "Rust" fn(@ExtCtxt,
|
||||
Span,
|
||||
@ast::MetaItem,
|
||||
~[@ast::item])
|
||||
-> ~[@ast::item];
|
||||
|
||||
pub type ItemDecoratorFun = @fn(@ExtCtxt,
|
||||
Span,
|
||||
@ast::MetaItem,
|
||||
~[@ast::item])
|
||||
-> ~[@ast::item];
|
||||
pub struct SyntaxExpanderTT {
|
||||
expander: SyntaxExpanderTTExpander,
|
||||
span: Option<Span>
|
||||
}
|
||||
|
||||
pub type SyntaxExpanderTTFun = @fn(@ExtCtxt,
|
||||
Span,
|
||||
&[ast::token_tree],
|
||||
ast::SyntaxContext)
|
||||
-> MacResult;
|
||||
pub trait SyntaxExpanderTTTrait {
|
||||
fn expand(&self,
|
||||
ecx: @ExtCtxt,
|
||||
span: Span,
|
||||
token_tree: &[ast::token_tree],
|
||||
context: ast::SyntaxContext)
|
||||
-> MacResult;
|
||||
}
|
||||
|
||||
pub type SyntaxExpanderTTItemFun = @fn(@ExtCtxt,
|
||||
Span,
|
||||
ast::Ident,
|
||||
~[ast::token_tree],
|
||||
ast::SyntaxContext)
|
||||
-> MacResult;
|
||||
pub type SyntaxExpanderTTFunNoCtxt =
|
||||
extern "Rust" fn(ecx: @ExtCtxt,
|
||||
span: codemap::Span,
|
||||
token_tree: &[ast::token_tree])
|
||||
-> MacResult;
|
||||
|
||||
// oog... in order to make the presentation of builtin_normal_tt_no_ctxt
|
||||
// and builtin_ident_tt_no_ctxt palatable, we need one-off types for
|
||||
// functions that don't consume a ctxt:
|
||||
enum SyntaxExpanderTTExpander {
|
||||
SyntaxExpanderTTExpanderWithoutContext(SyntaxExpanderTTFunNoCtxt),
|
||||
}
|
||||
|
||||
pub type SyntaxExpanderTTFunNoCtxt = @fn(@ExtCtxt,
|
||||
Span,
|
||||
&[ast::token_tree])
|
||||
-> MacResult;
|
||||
impl SyntaxExpanderTTTrait for SyntaxExpanderTT {
|
||||
fn expand(&self,
|
||||
ecx: @ExtCtxt,
|
||||
span: Span,
|
||||
token_tree: &[ast::token_tree],
|
||||
_: ast::SyntaxContext)
|
||||
-> MacResult {
|
||||
match self.expander {
|
||||
SyntaxExpanderTTExpanderWithoutContext(f) => {
|
||||
f(ecx, span, token_tree)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub type SyntaxExpanderTTItemFunNoCtxt = @fn(@ExtCtxt,
|
||||
Span,
|
||||
ast::Ident,
|
||||
~[ast::token_tree])
|
||||
-> MacResult;
|
||||
enum SyntaxExpanderTTItemExpander {
|
||||
SyntaxExpanderTTItemExpanderWithContext(SyntaxExpanderTTItemFun),
|
||||
SyntaxExpanderTTItemExpanderWithoutContext(SyntaxExpanderTTItemFunNoCtxt),
|
||||
}
|
||||
|
||||
pub struct SyntaxExpanderTTItem {
|
||||
expander: SyntaxExpanderTTItemExpander,
|
||||
span: Option<Span>
|
||||
}
|
||||
|
||||
pub trait SyntaxExpanderTTItemTrait {
|
||||
fn expand(&self,
|
||||
cx: @ExtCtxt,
|
||||
sp: Span,
|
||||
ident: ast::Ident,
|
||||
token_tree: ~[ast::token_tree],
|
||||
context: ast::SyntaxContext)
|
||||
-> MacResult;
|
||||
}
|
||||
|
||||
impl SyntaxExpanderTTItemTrait for SyntaxExpanderTTItem {
|
||||
fn expand(&self,
|
||||
cx: @ExtCtxt,
|
||||
sp: Span,
|
||||
ident: ast::Ident,
|
||||
token_tree: ~[ast::token_tree],
|
||||
context: ast::SyntaxContext)
|
||||
-> MacResult {
|
||||
match self.expander {
|
||||
SyntaxExpanderTTItemExpanderWithContext(fun) => {
|
||||
fun(cx, sp, ident, token_tree, context)
|
||||
}
|
||||
SyntaxExpanderTTItemExpanderWithoutContext(fun) => {
|
||||
fun(cx, sp, ident, token_tree)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub type SyntaxExpanderTTItemFun = extern "Rust" fn(@ExtCtxt,
|
||||
Span,
|
||||
ast::Ident,
|
||||
~[ast::token_tree],
|
||||
ast::SyntaxContext)
|
||||
-> MacResult;
|
||||
|
||||
pub type SyntaxExpanderTTItemFunNoCtxt =
|
||||
extern "Rust" fn(@ExtCtxt, Span, ast::Ident, ~[ast::token_tree])
|
||||
-> MacResult;
|
||||
|
||||
pub trait AnyMacro {
|
||||
fn make_expr(&self) -> @ast::Expr;
|
||||
fn make_item(&self) -> Option<@ast::item>;
|
||||
fn make_stmt(&self) -> @ast::Stmt;
|
||||
}
|
||||
|
||||
pub enum MacResult {
|
||||
MRExpr(@ast::Expr),
|
||||
MRItem(@ast::item),
|
||||
MRAny(@fn() -> @ast::Expr,
|
||||
@fn() -> Option<@ast::item>,
|
||||
@fn() -> @ast::Stmt),
|
||||
MRDef(MacroDef)
|
||||
MRAny(@AnyMacro),
|
||||
MRDef(MacroDef),
|
||||
}
|
||||
|
||||
pub enum SyntaxExtension {
|
||||
|
||||
// #[auto_encode] and such
|
||||
ItemDecorator(ItemDecoratorFun),
|
||||
ItemDecorator(ItemDecorator),
|
||||
|
||||
// Token-tree expanders
|
||||
NormalTT(SyntaxExpanderTTFun, Option<Span>),
|
||||
NormalTT(@SyntaxExpanderTTTrait, Option<Span>),
|
||||
|
||||
// An IdentTT is a macro that has an
|
||||
// identifier in between the name of the
|
||||
|
@ -98,7 +156,7 @@ pub enum SyntaxExtension {
|
|||
|
||||
// perhaps macro_rules! will lose its odd special identifier argument,
|
||||
// and this can go away also
|
||||
IdentTT(SyntaxExpanderTTItemFun, Option<Span>),
|
||||
IdentTT(@SyntaxExpanderTTItemTrait, Option<Span>),
|
||||
}
|
||||
|
||||
|
||||
|
@ -133,16 +191,22 @@ type RenameList = ~[(ast::Ident,Name)];
|
|||
// AST nodes into full ASTs
|
||||
pub fn syntax_expander_table() -> SyntaxEnv {
|
||||
// utility function to simplify creating NormalTT syntax extensions
|
||||
// that ignore their contexts
|
||||
fn builtin_normal_tt_no_ctxt(f: SyntaxExpanderTTFunNoCtxt) -> @Transformer {
|
||||
let wrapped_expander : SyntaxExpanderTTFun = |a,b,c,_d|{f(a,b,c)};
|
||||
@SE(NormalTT(wrapped_expander, None))
|
||||
fn builtin_normal_tt_no_ctxt(f: SyntaxExpanderTTFunNoCtxt)
|
||||
-> @Transformer {
|
||||
@SE(NormalTT(@SyntaxExpanderTT{
|
||||
expander: SyntaxExpanderTTExpanderWithoutContext(f),
|
||||
span: None,
|
||||
} as @SyntaxExpanderTTTrait,
|
||||
None))
|
||||
}
|
||||
// utility function to simplify creating IdentTT syntax extensions
|
||||
// that ignore their contexts
|
||||
fn builtin_item_tt_no_ctxt(f: SyntaxExpanderTTItemFunNoCtxt) -> @Transformer {
|
||||
let wrapped_expander : SyntaxExpanderTTItemFun = |a,b,c,d,_e|{f(a,b,c,d)};
|
||||
@SE(IdentTT(wrapped_expander, None))
|
||||
@SE(IdentTT(@SyntaxExpanderTTItem {
|
||||
expander: SyntaxExpanderTTItemExpanderWithoutContext(f),
|
||||
span: None,
|
||||
} as @SyntaxExpanderTTItemTrait,
|
||||
None))
|
||||
}
|
||||
let mut syntax_expanders = HashMap::new();
|
||||
// NB identifier starts with space, and can't conflict with legal idents
|
||||
|
@ -152,11 +216,17 @@ pub fn syntax_expander_table() -> SyntaxEnv {
|
|||
pending_renames : @mut ~[]
|
||||
}));
|
||||
syntax_expanders.insert(intern(&"macro_rules"),
|
||||
@SE(IdentTT(ext::tt::macro_rules::add_new_extension, None)));
|
||||
@SE(IdentTT(@SyntaxExpanderTTItem {
|
||||
expander: SyntaxExpanderTTItemExpanderWithContext(ext::tt::macro_rules::add_new_extension),
|
||||
span: None,
|
||||
} as @SyntaxExpanderTTItemTrait,
|
||||
None)));
|
||||
syntax_expanders.insert(intern(&"fmt"),
|
||||
builtin_normal_tt_no_ctxt(ext::fmt::expand_syntax_ext));
|
||||
builtin_normal_tt_no_ctxt(
|
||||
ext::fmt::expand_syntax_ext));
|
||||
syntax_expanders.insert(intern(&"format_args"),
|
||||
builtin_normal_tt_no_ctxt(ext::format::expand_args));
|
||||
builtin_normal_tt_no_ctxt(
|
||||
ext::format::expand_args));
|
||||
syntax_expanders.insert(
|
||||
intern(&"auto_encode"),
|
||||
@SE(ItemDecorator(ext::auto_encode::expand_auto_encode)));
|
||||
|
@ -164,67 +234,77 @@ pub fn syntax_expander_table() -> SyntaxEnv {
|
|||
intern(&"auto_decode"),
|
||||
@SE(ItemDecorator(ext::auto_encode::expand_auto_decode)));
|
||||
syntax_expanders.insert(intern(&"env"),
|
||||
builtin_normal_tt_no_ctxt(ext::env::expand_env));
|
||||
builtin_normal_tt_no_ctxt(
|
||||
ext::env::expand_env));
|
||||
syntax_expanders.insert(intern(&"option_env"),
|
||||
builtin_normal_tt_no_ctxt(ext::env::expand_option_env));
|
||||
builtin_normal_tt_no_ctxt(
|
||||
ext::env::expand_option_env));
|
||||
syntax_expanders.insert(intern("bytes"),
|
||||
builtin_normal_tt_no_ctxt(ext::bytes::expand_syntax_ext));
|
||||
builtin_normal_tt_no_ctxt(
|
||||
ext::bytes::expand_syntax_ext));
|
||||
syntax_expanders.insert(intern("concat_idents"),
|
||||
builtin_normal_tt_no_ctxt(
|
||||
ext::concat_idents::expand_syntax_ext));
|
||||
ext::concat_idents::expand_syntax_ext));
|
||||
syntax_expanders.insert(intern(&"log_syntax"),
|
||||
builtin_normal_tt_no_ctxt(
|
||||
ext::log_syntax::expand_syntax_ext));
|
||||
ext::log_syntax::expand_syntax_ext));
|
||||
syntax_expanders.insert(intern(&"deriving"),
|
||||
@SE(ItemDecorator(
|
||||
ext::deriving::expand_meta_deriving)));
|
||||
|
||||
// Quasi-quoting expanders
|
||||
syntax_expanders.insert(intern(&"quote_tokens"),
|
||||
builtin_normal_tt_no_ctxt(
|
||||
ext::quote::expand_quote_tokens));
|
||||
builtin_normal_tt_no_ctxt(
|
||||
ext::quote::expand_quote_tokens));
|
||||
syntax_expanders.insert(intern(&"quote_expr"),
|
||||
builtin_normal_tt_no_ctxt(ext::quote::expand_quote_expr));
|
||||
builtin_normal_tt_no_ctxt(
|
||||
ext::quote::expand_quote_expr));
|
||||
syntax_expanders.insert(intern(&"quote_ty"),
|
||||
builtin_normal_tt_no_ctxt(ext::quote::expand_quote_ty));
|
||||
builtin_normal_tt_no_ctxt(
|
||||
ext::quote::expand_quote_ty));
|
||||
syntax_expanders.insert(intern(&"quote_item"),
|
||||
builtin_normal_tt_no_ctxt(ext::quote::expand_quote_item));
|
||||
builtin_normal_tt_no_ctxt(
|
||||
ext::quote::expand_quote_item));
|
||||
syntax_expanders.insert(intern(&"quote_pat"),
|
||||
builtin_normal_tt_no_ctxt(ext::quote::expand_quote_pat));
|
||||
builtin_normal_tt_no_ctxt(
|
||||
ext::quote::expand_quote_pat));
|
||||
syntax_expanders.insert(intern(&"quote_stmt"),
|
||||
builtin_normal_tt_no_ctxt(ext::quote::expand_quote_stmt));
|
||||
builtin_normal_tt_no_ctxt(
|
||||
ext::quote::expand_quote_stmt));
|
||||
|
||||
syntax_expanders.insert(intern(&"line"),
|
||||
builtin_normal_tt_no_ctxt(
|
||||
ext::source_util::expand_line));
|
||||
ext::source_util::expand_line));
|
||||
syntax_expanders.insert(intern(&"col"),
|
||||
builtin_normal_tt_no_ctxt(
|
||||
ext::source_util::expand_col));
|
||||
ext::source_util::expand_col));
|
||||
syntax_expanders.insert(intern(&"file"),
|
||||
builtin_normal_tt_no_ctxt(
|
||||
ext::source_util::expand_file));
|
||||
ext::source_util::expand_file));
|
||||
syntax_expanders.insert(intern(&"stringify"),
|
||||
builtin_normal_tt_no_ctxt(
|
||||
ext::source_util::expand_stringify));
|
||||
ext::source_util::expand_stringify));
|
||||
syntax_expanders.insert(intern(&"include"),
|
||||
builtin_normal_tt_no_ctxt(
|
||||
ext::source_util::expand_include));
|
||||
ext::source_util::expand_include));
|
||||
syntax_expanders.insert(intern(&"include_str"),
|
||||
builtin_normal_tt_no_ctxt(
|
||||
ext::source_util::expand_include_str));
|
||||
ext::source_util::expand_include_str));
|
||||
syntax_expanders.insert(intern(&"include_bin"),
|
||||
builtin_normal_tt_no_ctxt(
|
||||
ext::source_util::expand_include_bin));
|
||||
ext::source_util::expand_include_bin));
|
||||
syntax_expanders.insert(intern(&"module_path"),
|
||||
builtin_normal_tt_no_ctxt(
|
||||
ext::source_util::expand_mod));
|
||||
ext::source_util::expand_mod));
|
||||
syntax_expanders.insert(intern(&"asm"),
|
||||
builtin_normal_tt_no_ctxt(ext::asm::expand_asm));
|
||||
builtin_normal_tt_no_ctxt(
|
||||
ext::asm::expand_asm));
|
||||
syntax_expanders.insert(intern(&"cfg"),
|
||||
builtin_normal_tt_no_ctxt(ext::cfg::expand_cfg));
|
||||
syntax_expanders.insert(
|
||||
intern(&"trace_macros"),
|
||||
builtin_normal_tt_no_ctxt(ext::trace_macros::expand_trace_macros));
|
||||
builtin_normal_tt_no_ctxt(
|
||||
ext::cfg::expand_cfg));
|
||||
syntax_expanders.insert(intern(&"trace_macros"),
|
||||
builtin_normal_tt_no_ctxt(
|
||||
ext::trace_macros::expand_trace_macros));
|
||||
MapChain::new(~syntax_expanders)
|
||||
}
|
||||
|
||||
|
|
|
@ -83,10 +83,12 @@ pub fn expand_expr(extsbox: @mut SyntaxEnv,
|
|||
let mac_span = original_span(cx);
|
||||
|
||||
let expanded =
|
||||
match expandfun(cx, mac_span.call_site,
|
||||
marked_before, marked_ctxt) {
|
||||
match expandfun.expand(cx,
|
||||
mac_span.call_site,
|
||||
marked_before,
|
||||
marked_ctxt) {
|
||||
MRExpr(e) => e,
|
||||
MRAny(expr_maker,_,_) => expr_maker(),
|
||||
MRAny(any_macro) => any_macro.make_expr(),
|
||||
_ => {
|
||||
cx.span_fatal(
|
||||
pth.span,
|
||||
|
@ -370,7 +372,7 @@ pub fn expand_item_mac(extsbox: @mut SyntaxEnv,
|
|||
// mark before expansion:
|
||||
let marked_before = mark_tts(tts,fm);
|
||||
let marked_ctxt = new_mark(fm,ctxt);
|
||||
expander(cx, it.span, marked_before, marked_ctxt)
|
||||
expander.expand(cx, it.span, marked_before, marked_ctxt)
|
||||
}
|
||||
Some(@SE(IdentTT(expander, span))) => {
|
||||
if it.ident.name == parse::token::special_idents::invalid.name {
|
||||
|
@ -388,7 +390,7 @@ pub fn expand_item_mac(extsbox: @mut SyntaxEnv,
|
|||
// mark before expansion:
|
||||
let marked_tts = mark_tts(tts,fm);
|
||||
let marked_ctxt = new_mark(fm,ctxt);
|
||||
expander(cx, it.span, it.ident, marked_tts, marked_ctxt)
|
||||
expander.expand(cx, it.span, it.ident, marked_tts, marked_ctxt)
|
||||
}
|
||||
_ => cx.span_fatal(
|
||||
it.span, fmt!("%s! is not legal in item position", extnamestr))
|
||||
|
@ -402,10 +404,10 @@ pub fn expand_item_mac(extsbox: @mut SyntaxEnv,
|
|||
MRExpr(_) => {
|
||||
cx.span_fatal(pth.span, fmt!("expr macro in item position: %s", extnamestr))
|
||||
}
|
||||
MRAny(_, item_maker, _) => {
|
||||
item_maker()
|
||||
.and_then(|i| mark_item(i,fm))
|
||||
.and_then(|i| fld.fold_item(i))
|
||||
MRAny(any_macro) => {
|
||||
any_macro.make_item()
|
||||
.and_then(|i| mark_item(i,fm))
|
||||
.and_then(|i| fld.fold_item(i))
|
||||
}
|
||||
MRDef(ref mdef) => {
|
||||
// yikes... no idea how to apply the mark to this. I'm afraid
|
||||
|
@ -481,17 +483,17 @@ pub fn expand_stmt(extsbox: @mut SyntaxEnv,
|
|||
// not the current mac.span.
|
||||
let mac_span = original_span(cx);
|
||||
|
||||
let expanded = match expandfun(cx,
|
||||
mac_span.call_site,
|
||||
marked_tts,
|
||||
marked_ctxt) {
|
||||
let expanded = match expandfun.expand(cx,
|
||||
mac_span.call_site,
|
||||
marked_tts,
|
||||
marked_ctxt) {
|
||||
MRExpr(e) => {
|
||||
@codemap::Spanned {
|
||||
node: StmtExpr(e, ast::DUMMY_NODE_ID),
|
||||
span: e.span,
|
||||
}
|
||||
}
|
||||
MRAny(_,_,stmt_mkr) => stmt_mkr(),
|
||||
MRAny(any_macro) => any_macro.make_stmt(),
|
||||
_ => cx.span_fatal(
|
||||
pth.span,
|
||||
fmt!("non-stmt macro in stmt pos: %s", extnamestr))
|
||||
|
|
|
@ -12,9 +12,9 @@ use ast::{Ident, matcher_, matcher, match_tok, match_nonterminal, match_seq};
|
|||
use ast::{tt_delim};
|
||||
use ast;
|
||||
use codemap::{Span, Spanned, dummy_sp};
|
||||
use ext::base::{ExtCtxt, MacResult, MRAny, MRDef, MacroDef, NormalTT};
|
||||
use ext::base::{AnyMacro, ExtCtxt, MacResult, MRAny, MRDef, MacroDef};
|
||||
use ext::base::{NormalTT, SyntaxExpanderTTTrait};
|
||||
use ext::base;
|
||||
use ext::expand;
|
||||
use ext::tt::macro_parser::{error};
|
||||
use ext::tt::macro_parser::{named_match, matched_seq, matched_nonterminal};
|
||||
use ext::tt::macro_parser::{parse, parse_or_else, success, failure};
|
||||
|
@ -24,6 +24,112 @@ use parse::token::{get_ident_interner, special_idents, gensym_ident, ident_to_st
|
|||
use parse::token::{FAT_ARROW, SEMI, nt_matchers, nt_tt};
|
||||
use print;
|
||||
|
||||
struct ParserAnyMacro {
|
||||
parser: @Parser,
|
||||
}
|
||||
|
||||
impl AnyMacro for ParserAnyMacro {
|
||||
fn make_expr(&self) -> @ast::Expr {
|
||||
self.parser.parse_expr()
|
||||
}
|
||||
fn make_item(&self) -> Option<@ast::item> {
|
||||
self.parser.parse_item(~[]) // no attrs
|
||||
}
|
||||
fn make_stmt(&self) -> @ast::Stmt {
|
||||
self.parser.parse_stmt(~[]) // no attrs
|
||||
}
|
||||
}
|
||||
|
||||
struct MacroRulesSyntaxExpanderTTFun {
|
||||
name: Ident,
|
||||
lhses: @~[@named_match],
|
||||
rhses: @~[@named_match],
|
||||
}
|
||||
|
||||
impl SyntaxExpanderTTTrait for MacroRulesSyntaxExpanderTTFun {
|
||||
fn expand(&self,
|
||||
cx: @ExtCtxt,
|
||||
sp: Span,
|
||||
arg: &[ast::token_tree],
|
||||
_: ast::SyntaxContext)
|
||||
-> MacResult {
|
||||
generic_extension(cx, sp, self.name, arg, *self.lhses, *self.rhses)
|
||||
}
|
||||
}
|
||||
|
||||
// Given `lhses` and `rhses`, this is the new macro we create
|
||||
fn generic_extension(cx: @ExtCtxt,
|
||||
sp: Span,
|
||||
name: Ident,
|
||||
arg: &[ast::token_tree],
|
||||
lhses: &[@named_match],
|
||||
rhses: &[@named_match])
|
||||
-> MacResult {
|
||||
if cx.trace_macros() {
|
||||
printfln!("%s! { %s }",
|
||||
cx.str_of(name),
|
||||
print::pprust::tt_to_str(
|
||||
&ast::tt_delim(@mut arg.to_owned()),
|
||||
get_ident_interner()));
|
||||
}
|
||||
|
||||
// Which arm's failure should we report? (the one furthest along)
|
||||
let mut best_fail_spot = dummy_sp();
|
||||
let mut best_fail_msg = ~"internal error: ran no matchers";
|
||||
|
||||
let s_d = cx.parse_sess().span_diagnostic;
|
||||
|
||||
for (i, lhs) in lhses.iter().enumerate() { // try each arm's matchers
|
||||
match *lhs {
|
||||
@matched_nonterminal(nt_matchers(ref mtcs)) => {
|
||||
// `none` is because we're not interpolating
|
||||
let arg_rdr = new_tt_reader(
|
||||
s_d,
|
||||
None,
|
||||
arg.to_owned()
|
||||
) as @mut reader;
|
||||
match parse(cx.parse_sess(), cx.cfg(), arg_rdr, *mtcs) {
|
||||
success(named_matches) => {
|
||||
let rhs = match rhses[i] {
|
||||
// okay, what's your transcriber?
|
||||
@matched_nonterminal(nt_tt(@ref tt)) => {
|
||||
match (*tt) {
|
||||
// cut off delimiters; don't parse 'em
|
||||
tt_delim(ref tts) => {
|
||||
(*tts).slice(1u,(*tts).len()-1u).to_owned()
|
||||
}
|
||||
_ => cx.span_fatal(
|
||||
sp, "macro rhs must be delimited")
|
||||
}
|
||||
},
|
||||
_ => cx.span_bug(sp, "bad thing in rhs")
|
||||
};
|
||||
// rhs has holes ( `$id` and `$(...)` that need filled)
|
||||
let trncbr = new_tt_reader(s_d, Some(named_matches),
|
||||
rhs);
|
||||
let p = @Parser(cx.parse_sess(),
|
||||
cx.cfg(),
|
||||
trncbr as @mut reader);
|
||||
|
||||
// Let the context choose how to interpret the result.
|
||||
// Weird, but useful for X-macros.
|
||||
return MRAny(@ParserAnyMacro {
|
||||
parser: p,
|
||||
} as @AnyMacro)
|
||||
}
|
||||
failure(sp, ref msg) => if sp.lo >= best_fail_spot.lo {
|
||||
best_fail_spot = sp;
|
||||
best_fail_msg = (*msg).clone();
|
||||
},
|
||||
error(sp, ref msg) => cx.span_fatal(sp, (*msg))
|
||||
}
|
||||
}
|
||||
_ => cx.bug("non-matcher found in parsed lhses")
|
||||
}
|
||||
}
|
||||
cx.span_fatal(best_fail_spot, best_fail_msg);
|
||||
}
|
||||
|
||||
// this procedure performs the expansion of the
|
||||
// macro_rules! macro. It parses the RHS and adds
|
||||
// an extension to the current context.
|
||||
|
@ -31,10 +137,8 @@ pub fn add_new_extension(cx: @ExtCtxt,
|
|||
sp: Span,
|
||||
name: Ident,
|
||||
arg: ~[ast::token_tree],
|
||||
stx_ctxt: ast::SyntaxContext)
|
||||
-> base::MacResult {
|
||||
let arg = expand::mtwt_cancel_outer_mark(arg,stx_ctxt);
|
||||
// Wrap a matcher_ in a spanned to produce a matcher.
|
||||
_: ast::SyntaxContext)
|
||||
-> base::MacResult {
|
||||
// these spans won't matter, anyways
|
||||
fn ms(m: matcher_) -> matcher {
|
||||
Spanned {
|
||||
|
@ -82,11 +186,13 @@ pub fn add_new_extension(cx: @ExtCtxt,
|
|||
};
|
||||
|
||||
// Given `lhses` and `rhses`, this is the new macro we create
|
||||
fn generic_extension(cx: @ExtCtxt, sp: Span, name: Ident,
|
||||
fn generic_extension(cx: @ExtCtxt,
|
||||
sp: Span,
|
||||
name: Ident,
|
||||
arg: &[ast::token_tree],
|
||||
lhses: &[@named_match], rhses: &[@named_match])
|
||||
-> MacResult {
|
||||
|
||||
lhses: &[@named_match],
|
||||
rhses: &[@named_match])
|
||||
-> MacResult {
|
||||
if cx.trace_macros() {
|
||||
printfln!("%s! { %s }",
|
||||
cx.str_of(name),
|
||||
|
@ -135,9 +241,9 @@ pub fn add_new_extension(cx: @ExtCtxt,
|
|||
|
||||
// Let the context choose how to interpret the result.
|
||||
// Weird, but useful for X-macros.
|
||||
return MRAny(|| p.parse_expr(),
|
||||
|| p.parse_item(~[/* no attrs*/]),
|
||||
|| p.parse_stmt(~[/* no attrs*/]));
|
||||
return MRAny(@ParserAnyMacro {
|
||||
parser: p
|
||||
} as @AnyMacro);
|
||||
}
|
||||
failure(sp, ref msg) => if sp.lo >= best_fail_spot.lo {
|
||||
best_fail_spot = sp;
|
||||
|
@ -152,10 +258,13 @@ pub fn add_new_extension(cx: @ExtCtxt,
|
|||
cx.span_fatal(best_fail_spot, best_fail_msg);
|
||||
}
|
||||
|
||||
let exp: @fn(@ExtCtxt, Span, &[ast::token_tree], ctxt: ast::SyntaxContext) -> MacResult =
|
||||
|cx, sp, arg, _ctxt| generic_extension(cx, sp, name, arg, *lhses, *rhses);
|
||||
let exp = @MacroRulesSyntaxExpanderTTFun {
|
||||
name: name,
|
||||
lhses: lhses,
|
||||
rhses: rhses,
|
||||
} as @SyntaxExpanderTTTrait;
|
||||
|
||||
return MRDef(MacroDef{
|
||||
return MRDef(MacroDef {
|
||||
name: ident_to_str(&name),
|
||||
ext: NormalTT(exp, Some(sp))
|
||||
});
|
||||
|
|
Loading…
Reference in New Issue