Skip to content

Commit

Permalink
Rollup merge of rust-lang#36669 - jseyfried:refactor_tok_result, r=nrc
Browse files Browse the repository at this point in the history
Unify `TokResult` and `ResultAnyMacro`

Fixes rust-lang#36641.
r? @nrc
  • Loading branch information
Jonathan Turner authored Sep 27, 2016
2 parents 96577e4 + df0e4bf commit 5cc9fb9
Show file tree
Hide file tree
Showing 4 changed files with 103 additions and 280 deletions.
143 changes: 1 addition & 142 deletions src/libsyntax/ext/base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,7 @@ use errors::DiagnosticBuilder;
use ext::expand::{self, Invocation, Expansion};
use ext::hygiene::Mark;
use fold::{self, Folder};
use parse;
use parse::parser::{self, Parser};
use parse::{self, parser};
use parse::token;
use parse::token::{InternedString, str_to_ident};
use ptr::P;
Expand Down Expand Up @@ -188,146 +187,6 @@ impl<F> AttrProcMacro for F
}
}

pub struct TokResult<'a> {
pub parser: Parser<'a>,
pub span: Span,
}

impl<'a> TokResult<'a> {
// There is quite a lot of overlap here with ParserAnyMacro in ext/tt/macro_rules.rs
// We could probably share more code.
// FIXME(#36641) Unify TokResult and ParserAnyMacro.
fn ensure_complete_parse(&mut self, allow_semi: bool) {
let macro_span = &self.span;
self.parser.ensure_complete_parse(allow_semi, |parser| {
let token_str = parser.this_token_to_string();
let msg = format!("macro expansion ignores token `{}` and any following", token_str);
let span = parser.span;
parser.diagnostic()
.struct_span_err(span, &msg)
.span_note(*macro_span, "caused by the macro expansion here")
.emit();
});
}
}

impl<'a> MacResult for TokResult<'a> {
fn make_items(mut self: Box<Self>) -> Option<SmallVector<P<ast::Item>>> {
if self.parser.sess.span_diagnostic.has_errors() {
return Some(SmallVector::zero());
}

let mut items = SmallVector::zero();
loop {
match self.parser.parse_item() {
Ok(Some(item)) => items.push(item),
Ok(None) => {
self.ensure_complete_parse(false);
return Some(items);
}
Err(mut e) => {
e.emit();
return Some(SmallVector::zero());
}
}
}
}

fn make_impl_items(mut self: Box<Self>) -> Option<SmallVector<ast::ImplItem>> {
let mut items = SmallVector::zero();
loop {
if self.parser.token == token::Eof {
break;
}
match self.parser.parse_impl_item() {
Ok(item) => items.push(item),
Err(mut e) => {
e.emit();
return Some(SmallVector::zero());
}
}
}
self.ensure_complete_parse(false);
Some(items)
}

fn make_trait_items(mut self: Box<Self>) -> Option<SmallVector<ast::TraitItem>> {
let mut items = SmallVector::zero();
loop {
if self.parser.token == token::Eof {
break;
}
match self.parser.parse_trait_item() {
Ok(item) => items.push(item),
Err(mut e) => {
e.emit();
return Some(SmallVector::zero());
}
}
}
self.ensure_complete_parse(false);
Some(items)
}

fn make_expr(mut self: Box<Self>) -> Option<P<ast::Expr>> {
match self.parser.parse_expr() {
Ok(e) => {
self.ensure_complete_parse(true);
Some(e)
}
Err(mut e) => {
e.emit();
Some(DummyResult::raw_expr(self.span))
}
}
}

fn make_pat(mut self: Box<Self>) -> Option<P<ast::Pat>> {
match self.parser.parse_pat() {
Ok(e) => {
self.ensure_complete_parse(false);
Some(e)
}
Err(mut e) => {
e.emit();
Some(P(DummyResult::raw_pat(self.span)))
}
}
}

fn make_stmts(mut self: Box<Self>) -> Option<SmallVector<ast::Stmt>> {
let mut stmts = SmallVector::zero();
loop {
if self.parser.token == token::Eof {
break;
}
match self.parser.parse_full_stmt(false) {
Ok(Some(stmt)) => stmts.push(stmt),
Ok(None) => { /* continue */ }
Err(mut e) => {
e.emit();
return Some(SmallVector::zero());
}
}
}
self.ensure_complete_parse(false);
Some(stmts)
}

fn make_ty(mut self: Box<Self>) -> Option<P<ast::Ty>> {
match self.parser.parse_ty() {
Ok(e) => {
self.ensure_complete_parse(false);
Some(e)
}
Err(mut e) => {
e.emit();
Some(DummyResult::raw_ty(self.span))
}
}
}
}

/// Represents a thing that maps token trees to Macro Results
pub trait TTMacroExpander {
fn expand<'cx>(&self,
Expand Down
108 changes: 86 additions & 22 deletions src/libsyntax/ext/expand.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
// except according to those terms.

use ast::{Block, Crate, Ident, Mac_, PatKind};
use ast::{MacStmtStyle, StmtKind, ItemKind};
use ast::{Name, MacStmtStyle, StmtKind, ItemKind};
use ast;
use ext::hygiene::Mark;
use ext::placeholders::{placeholder, PlaceholderExpander};
Expand All @@ -21,9 +21,9 @@ use ext::base::*;
use feature_gate::{self, Features};
use fold;
use fold::*;
use parse::{ParseSess, lexer};
use parse::{ParseSess, PResult, lexer};
use parse::parser::Parser;
use parse::token::{intern, keywords};
use parse::token::{self, intern, keywords};
use print::pprust;
use ptr::P;
use tokenstream::{TokenTree, TokenStream};
Expand All @@ -38,12 +38,12 @@ macro_rules! expansions {
($($kind:ident: $ty:ty [$($vec:ident, $ty_elt:ty)*], $kind_name:expr, .$make:ident,
$(.$fold:ident)* $(lift .$fold_elt:ident)*,
$(.$visit:ident)* $(lift .$visit_elt:ident)*;)*) => {
#[derive(Copy, Clone)]
#[derive(Copy, Clone, PartialEq, Eq)]
pub enum ExpansionKind { OptExpr, $( $kind, )* }
pub enum Expansion { OptExpr(Option<P<ast::Expr>>), $( $kind($ty), )* }

impl ExpansionKind {
fn name(self) -> &'static str {
pub fn name(self) -> &'static str {
match self {
ExpansionKind::OptExpr => "expression",
$( ExpansionKind::$kind => $kind_name, )*
Expand Down Expand Up @@ -106,6 +106,12 @@ macro_rules! expansions {
self.expand(Expansion::$kind(SmallVector::one(node))).$make()
})*)*
}

impl<'a> MacResult for ::ext::tt::macro_rules::ParserAnyMacro<'a> {
$(fn $make(self: Box<::ext::tt::macro_rules::ParserAnyMacro<'a>>) -> Option<$ty> {
Some(self.make(ExpansionKind::$kind).$make())
})*
}
}
}

Expand Down Expand Up @@ -293,10 +299,11 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
};

attr::mark_used(&attr);
let name = intern(&attr.name());
self.cx.bt_push(ExpnInfo {
call_site: attr.span,
callee: NameAndSpan {
format: MacroAttribute(intern(&attr.name())),
format: MacroAttribute(name),
span: Some(attr.span),
allow_internal_unstable: false,
}
Expand All @@ -319,14 +326,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
let item_toks = TokenStream::from_tts(tts_for_item(&item, &self.cx.parse_sess));

let tok_result = mac.expand(self.cx, attr.span, attr_toks, item_toks);
let parser = self.cx.new_parser_from_tts(&tok_result.to_tts());
let result = Box::new(TokResult { parser: parser, span: attr.span });

kind.make_from(result).unwrap_or_else(|| {
let msg = format!("macro could not be expanded into {} position", kind.name());
self.cx.span_err(attr.span, &msg);
kind.dummy(attr.span)
})
self.parse_expansion(tok_result, kind, name, attr.span)
}
_ => unreachable!(),
}
Expand Down Expand Up @@ -423,14 +423,9 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
},
});


let tok_result = expandfun.expand(self.cx,
span,
TokenStream::from_tts(marked_tts));
let parser = self.cx.new_parser_from_tts(&tok_result.to_tts());
let result = Box::new(TokResult { parser: parser, span: span });
// FIXME better span info.
kind.make_from(result).map(|i| i.fold_with(&mut ChangeSpan { span: span }))
let toks = TokenStream::from_tts(marked_tts);
let tok_result = expandfun.expand(self.cx, span, toks);
Some(self.parse_expansion(tok_result, kind, extname, span))
}
};

Expand All @@ -448,6 +443,75 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
expn_id: Some(self.cx.backtrace()),
})
}

fn parse_expansion(&mut self, toks: TokenStream, kind: ExpansionKind, name: Name, span: Span)
-> Expansion {
let mut parser = self.cx.new_parser_from_tts(&toks.to_tts());
let expansion = match parser.parse_expansion(kind, false) {
Ok(expansion) => expansion,
Err(mut err) => {
err.emit();
return kind.dummy(span);
}
};
parser.ensure_complete_parse(name, kind.name(), span);
// FIXME better span info
expansion.fold_with(&mut ChangeSpan { span: span })
}
}

impl<'a> Parser<'a> {
pub fn parse_expansion(&mut self, kind: ExpansionKind, macro_legacy_warnings: bool)
-> PResult<'a, Expansion> {
Ok(match kind {
ExpansionKind::Items => {
let mut items = SmallVector::zero();
while let Some(item) = self.parse_item()? {
items.push(item);
}
Expansion::Items(items)
}
ExpansionKind::TraitItems => {
let mut items = SmallVector::zero();
while self.token != token::Eof {
items.push(self.parse_trait_item()?);
}
Expansion::TraitItems(items)
}
ExpansionKind::ImplItems => {
let mut items = SmallVector::zero();
while self.token != token::Eof {
items.push(self.parse_impl_item()?);
}
Expansion::ImplItems(items)
}
ExpansionKind::Stmts => {
let mut stmts = SmallVector::zero();
while self.token != token::Eof {
if let Some(stmt) = self.parse_full_stmt(macro_legacy_warnings)? {
stmts.push(stmt);
}
}
Expansion::Stmts(stmts)
}
ExpansionKind::Expr => Expansion::Expr(self.parse_expr()?),
ExpansionKind::OptExpr => Expansion::OptExpr(Some(self.parse_expr()?)),
ExpansionKind::Ty => Expansion::Ty(self.parse_ty()?),
ExpansionKind::Pat => Expansion::Pat(self.parse_pat()?),
})
}

pub fn ensure_complete_parse(&mut self, macro_name: ast::Name, kind_name: &str, span: Span) {
if self.token != token::Eof {
let msg = format!("macro expansion ignores token `{}` and any following",
self.this_token_to_string());
let mut err = self.diagnostic().struct_span_err(self.span, &msg);
let msg = format!("caused by the macro expansion here; the usage \
of `{}!` is likely invalid in {} context",
macro_name, kind_name);
err.span_note(span, &msg).emit();
}
}
}

struct InvocationCollector<'a, 'b: 'a> {
Expand Down
Loading

0 comments on commit 5cc9fb9

Please sign in to comment.