Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Avoid some allocations in the macro parser #37318

Merged
merged 3 commits into from
Oct 22, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 14 additions & 7 deletions src/libsyntax/ext/tt/macro_parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -251,14 +251,22 @@ pub fn nameize(p_s: &ParseSess, ms: &[TokenTree], res: &[Rc<NamedMatch>])

pub enum ParseResult<T> {
Success(T),
/// Arm failed to match
Failure(syntax_pos::Span, String),
/// Arm failed to match. If the second parameter is `token::Eof`, it
/// indicates an unexpected end of macro invocation. Otherwise, it
/// indicates that no rules expected the given token.
Failure(syntax_pos::Span, Token),
/// Fatal error (malformed macro?). Abort compilation.
Error(syntax_pos::Span, String)
}

pub fn parse_failure_msg(tok: Token) -> String {
match tok {
token::Eof => "unexpected end of macro invocation".to_string(),
_ => format!("no rules expected the token `{}`", pprust::token_to_string(&tok)),
}
}

pub type NamedParseResult = ParseResult<HashMap<Ident, Rc<NamedMatch>>>;
pub type PositionalParseResult = ParseResult<Vec<Rc<NamedMatch>>>;

/// Perform a token equality check, ignoring syntax context (that is, an
/// unhygienic comparison)
Expand Down Expand Up @@ -425,8 +433,8 @@ pub fn parse(sess: &ParseSess,
cur_eis.push(ei);
}
TokenTree::Token(_, ref t) => {
let mut ei_t = ei.clone();
if token_name_eq(t,&tok) {
let mut ei_t = ei.clone();
ei_t.idx += 1;
next_eis.push(ei_t);
}
Expand All @@ -446,7 +454,7 @@ pub fn parse(sess: &ParseSess,
} else if eof_eis.len() > 1 {
return Error(sp, "ambiguity: multiple successful parses".to_string());
} else {
return Failure(sp, "unexpected end of macro invocation".to_string());
return Failure(sp, token::Eof);
}
} else {
if (!bb_eis.is_empty() && !next_eis.is_empty())
Expand All @@ -467,8 +475,7 @@ pub fn parse(sess: &ParseSess,
}
))
} else if bb_eis.is_empty() && next_eis.is_empty() {
return Failure(sp, format!("no rules expected the token `{}`",
pprust::token_to_string(&tok)));
return Failure(sp, tok);
} else if !next_eis.is_empty() {
/* Now process the next token */
while !next_eis.is_empty() {
Expand Down
19 changes: 12 additions & 7 deletions src/libsyntax/ext/tt/macro_rules.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ use ext::expand::{Expansion, ExpansionKind};
use ext::placeholders;
use ext::tt::macro_parser::{Success, Error, Failure};
use ext::tt::macro_parser::{MatchedSeq, MatchedNonterminal};
use ext::tt::macro_parser::parse;
use ext::tt::macro_parser::{parse, parse_failure_msg};
use parse::ParseSess;
use parse::lexer::new_tt_reader;
use parse::parser::{Parser, Restrictions};
Expand Down Expand Up @@ -100,7 +100,7 @@ fn generic_extension<'cx>(cx: &'cx ExtCtxt,

// 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".to_string();
let mut best_fail_tok = None;

for (i, lhs) in lhses.iter().enumerate() { // try each arm's matchers
let lhs_tt = match *lhs {
Expand Down Expand Up @@ -139,17 +139,18 @@ fn generic_extension<'cx>(cx: &'cx ExtCtxt,
macro_ident: name
})
}
Failure(sp, ref msg) => if sp.lo >= best_fail_spot.lo {
Failure(sp, tok) => if sp.lo >= best_fail_spot.lo {
best_fail_spot = sp;
best_fail_msg = (*msg).clone();
best_fail_tok = Some(tok);
},
Error(err_sp, ref msg) => {
cx.span_fatal(err_sp.substitute_dummy(sp), &msg[..])
}
}
}

cx.span_fatal(best_fail_spot.substitute_dummy(sp), &best_fail_msg[..]);
let best_fail_msg = parse_failure_msg(best_fail_tok.expect("ran no matchers"));
cx.span_fatal(best_fail_spot.substitute_dummy(sp), &best_fail_msg);
}

pub struct MacroRulesExpander;
Expand Down Expand Up @@ -227,8 +228,12 @@ pub fn compile(sess: &ParseSess, def: &ast::MacroDef) -> SyntaxExtension {

let argument_map = match parse(sess, &Vec::new(), arg_reader, &argument_gram) {
Success(m) => m,
Failure(sp, str) | Error(sp, str) => {
panic!(sess.span_diagnostic.span_fatal(sp.substitute_dummy(def.span), &str));
Failure(sp, tok) => {
let s = parse_failure_msg(tok);
panic!(sess.span_diagnostic.span_fatal(sp.substitute_dummy(def.span), &s));
}
Error(sp, s) => {
panic!(sess.span_diagnostic.span_fatal(sp.substitute_dummy(def.span), &s));
}
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ use syntax::ext::base::{ExtCtxt, MacResult, DummyResult, MacEager};
use syntax::ext::build::AstBuilder;
use syntax::ext::tt::macro_parser::{MatchedSeq, MatchedNonterminal};
use syntax::ext::tt::macro_parser::{Success, Failure, Error};
use syntax::ext::tt::macro_parser::parse_failure_msg;
use syntax::ptr::P;
use syntax_pos::Span;
use rustc_plugin::Registry;
Expand Down Expand Up @@ -58,8 +59,11 @@ fn expand_mbe_matches(cx: &mut ExtCtxt, sp: Span, args: &[TokenTree])
_ => unreachable!()
}
}
Failure(_, s) | Error(_, s) => {
panic!("expected Success, but got Error/Failure: {}", s);
Failure(_, tok) => {
panic!("expected Success, but got Failure: {}", parse_failure_msg(tok));
}
Error(_, s) => {
panic!("expected Success, but got Error: {}", s);
}
};

Expand Down